Hi,你們好,我是明哥。git
在本身學習 Golang 的這段時間裏,我寫了詳細的學習筆記放在個人我的微信公衆號 《Go編程時光》,對於 Go 語言,我也算是個初學者,所以寫的東西應該會比較適合剛接觸的同窗,若是你也是剛學習 Go 語言,不防關注一下,一塊兒學習,一塊兒成長。github
個人在線博客:http://golang.iswbm.com
個人 Github:github.com/iswbm/GolangCodingTimegolang
在以前學過的數據類型中,數組與切片,只能存儲同一類型的變量。若要存儲多個類型的變量,就須要用到結構體,它是將多個容易類型的命令變量組合在一塊兒的聚合數據類型。編程
每一個變量都成爲該結構體的成員變量。數組
能夠理解爲 Go語言 的結構體struct和其餘語言的class有相等的地位,可是Go語言放棄大量面向對象的特性,全部的Go語言類型除了指針類型外,均可以有本身的方法,提升了可擴展性。微信
在 Go 語言中沒有沒有 class 類的概念,只有 struct 結構體的概念,所以也沒有繼承,本篇文章,帶你學習一下結構體相關的內容。函數
聲明結構體性能
type 結構體名 struct { 屬性名 屬性類型 屬性名 屬性類型 ... }
好比我要定義一個能夠存儲我的資料名爲 Profile 的結構體,能夠這麼寫學習
type Profile struct { name string age int gender string mother *Profile // 指針 father *Profile // 指針 }
在 Go 語言中,咱們沒法在結構體內定義方法,那如何給一個結構體定義方法呢,答案是可使用組合函數的方式來定義結構體方法。它和普通函數的定義方式有些不同,好比下面這個方法雲計算
func (person Profile) FmtProfile() { fmt.Printf("名字:%s\n", person.name) fmt.Printf("年齡:%d\n", person.age) fmt.Printf("性別:%s\n", person.gender) }
其中fmt_profile
是方法名,而(person Profile)
:表示將 fmt_profile 方法與 Profile 的實例綁定。咱們把 Profile 稱爲方法的接收者,而 person 表示實例自己,它至關於 Python 中的 self,在方法內可使用 person.屬性名
的方法來訪問實例屬性。
完整代碼以下:
package main import "fmt" // 定義一個名爲Profile 的結構體 type Profile struct { name string age int gender string mother *Profile // 指針 father *Profile // 指針 } // 定義一個與 Profile 的綁定的方法 func (person Profile) FmtProfile() { fmt.Printf("名字:%s\n", person.name) fmt.Printf("年齡:%d\n", person.age) fmt.Printf("性別:%s\n", person.gender) } func main() { // 實例化 myself := Profile{name: "小明", age: 24, gender: "male"} // 調用函數 myself.FmtProfile() }
輸出以下
名字:小明 年齡:24 性別:male
上面定義方法的方式叫當你想要在方法內改變實例的屬性的時候,必須使用指針作爲方法的接收者。
package main import "fmt" // 聲明一個 Profile 的結構體 type Profile struct { name string age int gender string mother *Profile // 指針 father *Profile // 指針 } // 重點在於這個星號: * func (person *Profile) increase_age() { person.age += 1 } func main() { myself := Profile{name: "小明", age: 24, gender: "male"} fmt.Printf("當前年齡:%d\n", myself.age) myself.increase_age() fmt.Printf("當前年齡:%d", myself.age) }
輸出結果 以下,能夠看到在方法內部對 age 的修改已經生效。你能夠嘗試去掉 *
,使用值作爲方法接收者,看看age是否會發生改變。
當前年齡:24 當前年齡:25
至此,咱們知道了兩種定義方法的方式:
那咱們如何進行選擇呢?如下幾種狀況,應當直接使用指針作爲方法的接收者。
有些狀況下,以值或指針作爲接收者均可以,可是考慮到代碼一致性,建議都使用指針作爲接收者。
無論你使用哪一種方法定義方法,指針實例對象、值實例對象均可以直接調用,而沒有什麼約束。這一點Go語言作得很是好。
爲何標題的繼承,加了雙引號,由於Go 語言自己並不支持繼承。
但咱們可使用組合的方法,實現相似繼承的效果。
在生活中,組合的例子很是多,好比一臺電腦,是由機身外殼,主板,CPU,內存等零部件組合在一塊兒,最後纔有了咱們用的電腦。
一樣的,在 Go 語言中,把一個結構體嵌入到另外一個結構體的方法,稱之爲組合。
如今這裏有一個表示公司(company)的結構體,還有一個表示公司職員(staff)的結構體。
type company struct { companyName string companyAddr string } type staff struct { name string age int gender string position string }
若要將公司信息與公司職員關聯起來,通常都會想到將 company 結構體的內容照抄到 staff 裏。
type staff struct { name string age int gender string companyName string companyAddr string position string }
雖然在實現上並無什麼問題,但在你對同一公司的多個staff初始化的時候,都得重複初始化相同的公司信息,這作得並很差,借鑑繼承的思想,咱們能夠將公司的屬性都「繼承」過來。
可是在 Go 中沒有類的概念,只有組合,你能夠將 company 這個 結構體嵌入到 staff 中,作爲 staff 的一個匿名字段,staff 就直接擁有了 company 的全部屬性了。
type staff struct { name string age int gender string position string company // 匿名字段 }
來寫個完整的程序驗證一下。
package main import "fmt" type company struct { companyName string companyAddr string } type staff struct { name string age int gender string position string company } func main() { myCom := company{ companyName: "Tencent", companyAddr: "深圳市南山區", } staffInfo := staff{ name: "小明", age: 28, gender: "男", position: "雲計算開發工程師", company: myCom, } fmt.Printf("%s 在 %s 工做\n", staffInfo.name, staffInfo.companyName) fmt.Printf("%s 在 %s 工做\n", staffInfo.name, staffInfo.company.companyName) }
輸出結果以下,可見staffInfo.companyName
和 staffInfo.company.companyName
的效果是同樣的。
小明 在 Tencent 工做 小明 在 Tencent 工做
在 Go 語言中,函數名的首字母大小寫很是重要,它被來實現控制對方法的訪問權限。
系列導讀