go 修改结构体方法_「GCTT 出品」Go 系列教程——26. 结构体取代类
Go語言中文網,致力于每日分享編碼、開源等知識,歡迎關注我,會有意想不到的收獲!
Go 支持面向對象嗎?
Go 并不是完全面向對象的編程語言。Go 官網的 FAQ 回答了 Go 是否是面向對象語言,摘錄如下。
可以說是,也可以說不是。雖然 Go 有類型和方法,支持面向對象的編程風格,但卻沒有類型的層次結構。Go 中的“接口”概念提供了一種不同的方法,我們認為它易于使用,也更為普遍。Go 也可以將結構體嵌套使用,這與子類化(Subclassing)類似,但并不完全相同。此外,Go 提供的特性比 C++ 或 Java 更為通用:子類可以由任何類型的數據來定義,甚至是內建類型(如簡單的“未裝箱的”整型)。這在結構體(類)中沒有受到限制。
在接下來的教程里,我們會討論如何使用 Go 來實現面向對象編程概念。與其它面向對象語言(如 Java)相比,Go 有很多完全不同的特性。
使用結構體,而非類
Go 不支持類,而是提供了結構體。結構體中可以添加方法。這樣可以將數據和操作數據的方法綁定在一起,實現與類相似的效果。
為了加深理解,我們來編寫一個示例吧。
在示例中,我們創建一個自定義包,它幫助我們更好地理解,結構體是如何有效地取代類的。
在你的 Go 工作區創建一個名為 oop 的文件夾。在 opp 中再創建子文件夾 employee。在 employee 內,創建一個名為 employee.go 的文件。
文件夾結構會是這樣:
workspacepath -> oop -> employee -> employee.go請將 employee.go 里的內容替換為如下所示的代碼。
在上述程序里,第 1 行指定了該文件屬于 employee 包。而第 7 行聲明了一個 Employee 結構體。在第 14 行,結構體 Employee 添加了一個名為 LeavesRemaining 的方法。該方法會計算和顯示員工的剩余休假數。于是現在我們有了一個結構體,并綁定了結構體的方法,這與類很相似。
接著在 oop 文件夾里創建一個文件,命名為 main.go。
現在目錄結構如下所示:
main.go 的內容如下所示:
我們在第 3 行引用了 employee 包。在 main()(第 12 行),我們調用了 Employee 的 LeavesRemaining() 方法。
由于有自定義包,這個程序不能在 go playground 上運行。你可以在你的本地運行,在 workspacepath/bin/oop 下輸入命令 go install opp,程序會打印輸出:
Sam Adolf has 10 leaves remaining使用 New() 函數,而非構造器
我們上面寫的程序看起來沒什么問題,但還是有一些細節問題需要注意。我們看看當定義一個零值的 employee 結構體變量時,會發生什么。將 main.go 的內容修改為如下代碼:
我們的修改只是創建一個零值的 Employee 結構體變量(第 6 行)。該程序會輸出:
has 0 leaves remaining你可以看到,使用 Employee 創建的零值變量沒有什么用。它沒有合法的姓名,也沒有合理的休假細節。
在像 Java 這樣的 OOP 語言中,是使用構造器來解決這種問題的。一個合法的對象必須使用參數化的構造器來創建。
Go 并不支持構造器。如果某類型的零值不可用,需要程序員來隱藏該類型,避免從其他包直接訪問。程序員應該提供一種名為 NewT(parameters) 的 函數,按照要求來初始化 T 類型的變量。按照 Go 的慣例,應該把創建 T 類型變量的函數命名為 NewT(parameters)。這就類似于構造器了。如果一個包只含有一種類型,按照 Go 的慣例,應該把函數命名為 New(parameters), 而不是 NewT(parameters)。
讓我修改一下原先的代碼,使得每當創建 employee 的時候,它都是可用的。
首先應該讓 Employee 結構體不可引用,然后創建一個 New 函數,用于創建 Employee 結構體變量。在 employee.go 中輸入下面代碼:
我們進行了一些重要的修改。我們把 Employee 結構體的首字母改為小寫 e,也就是將 type Employee struct 改為了 type employee struct。通過這種方法,我們把 employee 結構體變為了不可引用的,防止其他包對它的訪問。除非有特殊需求,否則也要隱藏所有不可引用的結構體的所有字段,這是 Go 的最佳實踐。由于我們不會在外部包需要 employee 的字段,因此我們也讓這些字段無法引用。
同樣,我們還修改了 LeavesRemaining() 的方法。
現在由于 employee 不可引用,因此不能在其他包內直接創建 Employee 類型的變量。于是我們在第 14 行提供了一個可引用的 New 函數,該函數接收必要的參數,返回一個新創建的 employee 結構體變量。
這個程序還需要一些必要的修改,但現在先運行這個程序,理解一下當前的修改。如果運行當前程序,編譯器會報錯,如下所示:
go/src/constructor/main.go:6: undefined: employee.Employee這是因為我們將 Employee 設置為不可引用,因此編譯器會報錯,提示該類型沒有在 main.go 中定義。很完美,正如我們期望的一樣,其他包現在不能輕易創建零值的 employee 變量了。我們成功地避免了創建不可用的 employee 結構體變量。現在創建 employee 變量的唯一方法就是使用 New 函數。
如下所示,修改 main.go 里的內容。
該文件唯一的修改就是第 6 行。通過向 New 函數傳入所需變量,我們創建了一個新的 employee 結構體變量。
下面是修改后的兩個文件的內容。
main.go
運行該程序,會輸出:
Sam Adolf has 10 leaves remaining現在你能明白了,雖然 Go 不支持類,但結構體能夠很好地取代類,而以 New(parameters) 簽名的方法可以替代構造器。
關于 Go 中的類和構造器到此結束。祝你愉快。
上一教程 - 「GCTT 出品」Go 系列教程——25. Mutex
下一教程 - 組合取代繼承
歷史文章:
「GCTT 出品」Go 系列教程——1. 介紹與安裝
「GCTT 出品」Go 系列教程——2. Hello World
「GCTT 出品」Go 系列教程——3. 變量
「GCTT 出品」Go 系列教程——4. 類型
「GCTT 出品」Go 系列教程——5. 常量
「GCTT 出品」Go 系列教程——6. 函數(Function)
「GCTT 出品」Go 系列教程——7. 包
Go 系列教程——8. if-else 語句
「GCTT 出品」Go 系列教程——9. 循環
「GCTT 出品」Go 系列教程——10. switch 語句
「GCTT 出品」Go 系列教程——11. 數組和切片
「GCTT 出品」Go 系列教程——12. 可變參數函數
「GCTT 出品」Go 系列教程——13. Maps
「GCTT 出品」Go 系列教程——14. 字符串
「GCTT 出品」Go 系列教程——15. 指針
「GCTT 出品」Go 系列教程——16. 結構體,這一篇就夠
「GCTT 出品」Go 系列教程——17. 超全的方法教程
「GCTT 出品」Go 系列教程——18. 接口(一)
「GCTT 出品」Go 系列教程——19. 接口(二)
「GCTT 出品」Go 系列教程——20. 并發入門
「GCTT 出品」Go 系列教程——21. Go 協程
「GCTT 出品」Go 系列教程——22. 信道(channel)
「GCTT 出品」Go 系列教程——23. 緩沖信道和工作池
「GCTT 出品」Go 系列教程——24. Select
「GCTT 出品」Go 系列教程——25. Mutex
總結
以上是生活随笔為你收集整理的go 修改结构体方法_「GCTT 出品」Go 系列教程——26. 结构体取代类的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 北京环球影城晚上有灯么
- 下一篇: java实现红包要多少钱_java实现红