Go 面向对象之结构体
生活随笔
收集整理的這篇文章主要介紹了
Go 面向对象之结构体
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
#### Go 面向?qū)ο笾Y(jié)構(gòu)體
最近有四天沒(méi)更新公眾號(hào),有一些事情耽誤了,生活就是這樣,總會(huì)一些事情讓人措不及防;
***山濃水淺,坐看流年***
1. Go 也支持面向?qū)ο缶幊?OOP) 但是它和傳統(tǒng)的面向?qū)ο缶幊踢€是有一些區(qū)別,并不是純粹的面向?qū)ο缶幊?
2. Go 中沒(méi)有類(lèi)(class), Go 中struct 和其它編程語(yǔ)言中的類(lèi)有同等地位,所以我們可以理解Go 是基于struct 來(lái)實(shí)現(xiàn)OOP;
3. Go 面向?qū)ο蠛芎?jiǎn)潔,沒(méi)有傳統(tǒng)OOP 的繼承,方法重載,構(gòu)造函數(shù)等等;
4. Go 面向?qū)ο笕杂欣^承,封裝,多態(tài)的特性,只是它的實(shí)現(xiàn)與傳統(tǒng)的OOP語(yǔ)言不同;
##### 結(jié)構(gòu)體與結(jié)構(gòu)體變量(實(shí)例/對(duì)象)的關(guān)系圖
---
說(shuō)明:
1. 將一類(lèi)事物的特性提取出來(lái)(比如貓類(lèi)),形成一個(gè)新的數(shù)據(jù)類(lèi)型就是一個(gè)結(jié)構(gòu)體;
2. 通過(guò)這個(gè)結(jié)構(gòu)體,可以創(chuàng)建多個(gè)變量(實(shí)例/對(duì)象);
3. 事物可以是貓類(lèi),也可以是其它的類(lèi)...;
案例: package mainimport "fmt"// 定義一個(gè)結(jié)構(gòu)體,類(lèi)似于類(lèi) // 將Cat 的各個(gè)字段/屬性,放入到結(jié)構(gòu)體中 type Cat struct {Name stringAge uintColor stringHobby string } func main(){// 聲明一個(gè)Cat 變量,也就是實(shí)例var a1 Cata1.Name = "小花"a1.Age = 2a1.Color = "black"a1.Hobby = "老鼠"fmt.Println(a1)fmt.Printf("name=%s\n",a1.Name)fmt.Printf("age=%d\n",a1.Age)fmt.Printf("color=%s\n",a1.Color)fmt.Printf("hobby=%s\n",a1.Hobby) }
---
結(jié)構(gòu)體與結(jié)構(gòu)體變量(實(shí)例)的區(qū)別
1. 結(jié)構(gòu)體是自定義的數(shù)據(jù)類(lèi)型,代表一類(lèi)事物;
2. 結(jié)構(gòu)體變量是具體的,實(shí)際的,代表一個(gè)具體的變量;
---
##### 結(jié)構(gòu)體變量在內(nèi)存中的布局
##### 如何聲明結(jié)構(gòu)體
基本語(yǔ)法:
type 結(jié)構(gòu)體名稱(chēng) struct {
field1 type
field2 type
...
}
例如:
typt Person struct {
Name string
Age int
Class string
}
##### 字段屬性
字段是結(jié)構(gòu)體的組成部分,一般是基本數(shù)據(jù)類(lèi)型,數(shù)組,同時(shí)也可以是引用類(lèi)型;
注意事項(xiàng):
1. 字段聲明語(yǔ)法同變量一樣: 字段名 字段類(lèi)型
2. 在創(chuàng)建一個(gè)結(jié)構(gòu)體變量后,如果沒(méi)有給字段賦值,每個(gè)字段都對(duì)應(yīng)一個(gè)默認(rèn)值,引用類(lèi)型默認(rèn)值為nil;
3. 不同結(jié)構(gòu)體變量的字段是獨(dú)立的,互不影響: 結(jié)構(gòu)體是值類(lèi)型; package mainimport "fmt"// 如果結(jié)構(gòu)體里的字段是引用類(lèi)型的: slice map channel; // 在使用前需要make分配內(nèi)存才能使用; type Person struct {Name stringAge intHobby [3]stringptr *stringslice []intParents map[string]string } type Cat struct {Name stringAge int } func main(){var a1 Personfmt.Println(a1) //{0 [] nil [] map[]}if a1.ptr == nil {fmt.Println("ptr is nil")}if a1.slice == nil {fmt.Println("slice is nil")}if a1.Parents == nil {fmt.Println("parents is nil")}// 結(jié)構(gòu)體字段是引用類(lèi)型的話(huà),使用前需要makea1.slice = make([]int,10)a1.slice[0] = 1a1.slice[1] = 2a1.slice[2] = 3a1.Parents = make(map[string]string)a1.Parents["name"] = "aaaa"a1.Parents["friendly"] = "father"fmt.Println(a1) // { 0 [ ] <nil> [1 2 3 0 0 0 0 0 0 0] map[friendly:father name:aaaa]}// 不同結(jié)構(gòu)體變量間互不影響var c1 Catvar c2 Catc1.Name = "c1"c2.Name = "c2"c1.Age = 1c2.Age = 2fmt.Println(c1,c2) //{c1 1} {c2 2} }
---
##### 創(chuàng)建結(jié)構(gòu)變量和訪問(wèn)結(jié)構(gòu)體字段 package mainimport "fmt"type Cat struct {Name stringAge int } func main(){// 方式1: 先聲明,再賦值var c1 Catc1.Name = "c1"c1.Age = 1fmt.Println(c1) //{c1 1}// 方式2: 字面量方式var c2 Cat = Cat{"c2",2}fmt.Println(c2) //{c2 2}// 方式3: 類(lèi)型推導(dǎo)方式c3 := Cat{"c3",3}fmt.Println(c3) //{c3 3}// 方式4: new 方式var c4 *Cat = new(Cat)c4.Name = "c4"c4.Age = 4fmt.Println(*c4)// 方式5: &{} 方式var c5 *Cat = &Cat{}c5.Name = "c5"c5.Age = 5fmt.Println(*c5)// 方式4,方式5 返回的都是結(jié)構(gòu)體的指針類(lèi)型 }
1. 第4,5 種方式返回的是***結(jié)構(gòu)體指針***;
2. 結(jié)構(gòu)體指針訪問(wèn)字段的標(biāo)準(zhǔn)方式應(yīng)該是:(*結(jié)構(gòu)體指針).字段名, 如:(*c4).Name = "c4";
3. Go 做了簡(jiǎn)化,支持***結(jié)構(gòu)體指針.字段名***,如:c4.Name = "c4",Go 編譯器底層自動(dòng)處理了;
---
##### 結(jié)構(gòu)體使用注意事項(xiàng)
1. 結(jié)構(gòu)體中所有的字段在內(nèi)存中是連續(xù)的;
2. 結(jié)構(gòu)體是用戶(hù)自定義的類(lèi)型,在和其它類(lèi)型轉(zhuǎn)換時(shí)需要有完全相同的字段(名稱(chēng),個(gè)數(shù),類(lèi)型);
3. 結(jié)構(gòu)體進(jìn)行type 定義,Go 認(rèn)為是新的數(shù)據(jù)類(lèi)型,可以和基本數(shù)據(jù)類(lèi)型進(jìn)行強(qiáng)轉(zhuǎn);
4. 結(jié)構(gòu)體每個(gè)字段上可以寫(xiě)tag,tag 可以通過(guò)反射機(jī)制獲取,常用的場(chǎng)景是序列化和反序列化; package mainimport ("encoding/json""fmt" )type Person struct {Name stringAge intHobby string } type Student struct {Name stringAge intHobby string } type Cat struct {Name string `json:"name"`Age int `json:"age"` } func main(){var p1 Personp1.Name = "p1"p1.Age = 22p1.Hobby = "run"// 結(jié)構(gòu)體變量的地址fmt.Printf("p1 address: %p\n",&p1)fmt.Printf("p1.Name address: %p\n",&p1.Name) // 0xc0000562d0fmt.Printf("p1.Age address: %p\n",&p1.Age) // 0xc0000562e0 , 一個(gè)string 是16 字節(jié)fmt.Printf("p1.Hobby address: %p\n",&p1.Hobby)//0xc0000562e8 , 一個(gè)int 在64 位系統(tǒng)中為8字節(jié)// 類(lèi)型之間強(qiáng)轉(zhuǎn)var s1 Students1 = Student(p1)fmt.Println(s1)fmt.Printf("s1 type is %T\n",s1) // Student// struct tagvar c1 Catc1.Name = "小花"c1.Age = 12jsonStr,err := json.Marshal(c1)if err != nil {fmt.Println(err)}// 輸出的是結(jié)構(gòu)體中tag 定義的名稱(chēng)fmt.Println(string(jsonStr)) // {"name":"小花","age":12} }
最近有四天沒(méi)更新公眾號(hào),有一些事情耽誤了,生活就是這樣,總會(huì)一些事情讓人措不及防;
***山濃水淺,坐看流年***
1. Go 也支持面向?qū)ο缶幊?OOP) 但是它和傳統(tǒng)的面向?qū)ο缶幊踢€是有一些區(qū)別,并不是純粹的面向?qū)ο缶幊?
2. Go 中沒(méi)有類(lèi)(class), Go 中struct 和其它編程語(yǔ)言中的類(lèi)有同等地位,所以我們可以理解Go 是基于struct 來(lái)實(shí)現(xiàn)OOP;
3. Go 面向?qū)ο蠛芎?jiǎn)潔,沒(méi)有傳統(tǒng)OOP 的繼承,方法重載,構(gòu)造函數(shù)等等;
4. Go 面向?qū)ο笕杂欣^承,封裝,多態(tài)的特性,只是它的實(shí)現(xiàn)與傳統(tǒng)的OOP語(yǔ)言不同;
##### 結(jié)構(gòu)體與結(jié)構(gòu)體變量(實(shí)例/對(duì)象)的關(guān)系圖
---
說(shuō)明:
1. 將一類(lèi)事物的特性提取出來(lái)(比如貓類(lèi)),形成一個(gè)新的數(shù)據(jù)類(lèi)型就是一個(gè)結(jié)構(gòu)體;
2. 通過(guò)這個(gè)結(jié)構(gòu)體,可以創(chuàng)建多個(gè)變量(實(shí)例/對(duì)象);
3. 事物可以是貓類(lèi),也可以是其它的類(lèi)...;
案例: package mainimport "fmt"// 定義一個(gè)結(jié)構(gòu)體,類(lèi)似于類(lèi) // 將Cat 的各個(gè)字段/屬性,放入到結(jié)構(gòu)體中 type Cat struct {Name stringAge uintColor stringHobby string } func main(){// 聲明一個(gè)Cat 變量,也就是實(shí)例var a1 Cata1.Name = "小花"a1.Age = 2a1.Color = "black"a1.Hobby = "老鼠"fmt.Println(a1)fmt.Printf("name=%s\n",a1.Name)fmt.Printf("age=%d\n",a1.Age)fmt.Printf("color=%s\n",a1.Color)fmt.Printf("hobby=%s\n",a1.Hobby) }
---
結(jié)構(gòu)體與結(jié)構(gòu)體變量(實(shí)例)的區(qū)別
1. 結(jié)構(gòu)體是自定義的數(shù)據(jù)類(lèi)型,代表一類(lèi)事物;
2. 結(jié)構(gòu)體變量是具體的,實(shí)際的,代表一個(gè)具體的變量;
---
##### 結(jié)構(gòu)體變量在內(nèi)存中的布局
##### 如何聲明結(jié)構(gòu)體
基本語(yǔ)法:
type 結(jié)構(gòu)體名稱(chēng) struct {
field1 type
field2 type
...
}
例如:
typt Person struct {
Name string
Age int
Class string
}
##### 字段屬性
字段是結(jié)構(gòu)體的組成部分,一般是基本數(shù)據(jù)類(lèi)型,數(shù)組,同時(shí)也可以是引用類(lèi)型;
注意事項(xiàng):
1. 字段聲明語(yǔ)法同變量一樣: 字段名 字段類(lèi)型
2. 在創(chuàng)建一個(gè)結(jié)構(gòu)體變量后,如果沒(méi)有給字段賦值,每個(gè)字段都對(duì)應(yīng)一個(gè)默認(rèn)值,引用類(lèi)型默認(rèn)值為nil;
3. 不同結(jié)構(gòu)體變量的字段是獨(dú)立的,互不影響: 結(jié)構(gòu)體是值類(lèi)型; package mainimport "fmt"// 如果結(jié)構(gòu)體里的字段是引用類(lèi)型的: slice map channel; // 在使用前需要make分配內(nèi)存才能使用; type Person struct {Name stringAge intHobby [3]stringptr *stringslice []intParents map[string]string } type Cat struct {Name stringAge int } func main(){var a1 Personfmt.Println(a1) //{0 [] nil [] map[]}if a1.ptr == nil {fmt.Println("ptr is nil")}if a1.slice == nil {fmt.Println("slice is nil")}if a1.Parents == nil {fmt.Println("parents is nil")}// 結(jié)構(gòu)體字段是引用類(lèi)型的話(huà),使用前需要makea1.slice = make([]int,10)a1.slice[0] = 1a1.slice[1] = 2a1.slice[2] = 3a1.Parents = make(map[string]string)a1.Parents["name"] = "aaaa"a1.Parents["friendly"] = "father"fmt.Println(a1) // { 0 [ ] <nil> [1 2 3 0 0 0 0 0 0 0] map[friendly:father name:aaaa]}// 不同結(jié)構(gòu)體變量間互不影響var c1 Catvar c2 Catc1.Name = "c1"c2.Name = "c2"c1.Age = 1c2.Age = 2fmt.Println(c1,c2) //{c1 1} {c2 2} }
---
##### 創(chuàng)建結(jié)構(gòu)變量和訪問(wèn)結(jié)構(gòu)體字段 package mainimport "fmt"type Cat struct {Name stringAge int } func main(){// 方式1: 先聲明,再賦值var c1 Catc1.Name = "c1"c1.Age = 1fmt.Println(c1) //{c1 1}// 方式2: 字面量方式var c2 Cat = Cat{"c2",2}fmt.Println(c2) //{c2 2}// 方式3: 類(lèi)型推導(dǎo)方式c3 := Cat{"c3",3}fmt.Println(c3) //{c3 3}// 方式4: new 方式var c4 *Cat = new(Cat)c4.Name = "c4"c4.Age = 4fmt.Println(*c4)// 方式5: &{} 方式var c5 *Cat = &Cat{}c5.Name = "c5"c5.Age = 5fmt.Println(*c5)// 方式4,方式5 返回的都是結(jié)構(gòu)體的指針類(lèi)型 }
1. 第4,5 種方式返回的是***結(jié)構(gòu)體指針***;
2. 結(jié)構(gòu)體指針訪問(wèn)字段的標(biāo)準(zhǔn)方式應(yīng)該是:(*結(jié)構(gòu)體指針).字段名, 如:(*c4).Name = "c4";
3. Go 做了簡(jiǎn)化,支持***結(jié)構(gòu)體指針.字段名***,如:c4.Name = "c4",Go 編譯器底層自動(dòng)處理了;
---
##### 結(jié)構(gòu)體使用注意事項(xiàng)
1. 結(jié)構(gòu)體中所有的字段在內(nèi)存中是連續(xù)的;
2. 結(jié)構(gòu)體是用戶(hù)自定義的類(lèi)型,在和其它類(lèi)型轉(zhuǎn)換時(shí)需要有完全相同的字段(名稱(chēng),個(gè)數(shù),類(lèi)型);
3. 結(jié)構(gòu)體進(jìn)行type 定義,Go 認(rèn)為是新的數(shù)據(jù)類(lèi)型,可以和基本數(shù)據(jù)類(lèi)型進(jìn)行強(qiáng)轉(zhuǎn);
4. 結(jié)構(gòu)體每個(gè)字段上可以寫(xiě)tag,tag 可以通過(guò)反射機(jī)制獲取,常用的場(chǎng)景是序列化和反序列化; package mainimport ("encoding/json""fmt" )type Person struct {Name stringAge intHobby string } type Student struct {Name stringAge intHobby string } type Cat struct {Name string `json:"name"`Age int `json:"age"` } func main(){var p1 Personp1.Name = "p1"p1.Age = 22p1.Hobby = "run"// 結(jié)構(gòu)體變量的地址fmt.Printf("p1 address: %p\n",&p1)fmt.Printf("p1.Name address: %p\n",&p1.Name) // 0xc0000562d0fmt.Printf("p1.Age address: %p\n",&p1.Age) // 0xc0000562e0 , 一個(gè)string 是16 字節(jié)fmt.Printf("p1.Hobby address: %p\n",&p1.Hobby)//0xc0000562e8 , 一個(gè)int 在64 位系統(tǒng)中為8字節(jié)// 類(lèi)型之間強(qiáng)轉(zhuǎn)var s1 Students1 = Student(p1)fmt.Println(s1)fmt.Printf("s1 type is %T\n",s1) // Student// struct tagvar c1 Catc1.Name = "小花"c1.Age = 12jsonStr,err := json.Marshal(c1)if err != nil {fmt.Println(err)}// 輸出的是結(jié)構(gòu)體中tag 定義的名稱(chēng)fmt.Println(string(jsonStr)) // {"name":"小花","age":12} }
個(gè)人微信公眾號(hào)上有最新內(nèi)容,歡迎關(guān)注交流學(xué)習(xí)
轉(zhuǎn)載于:https://www.cnblogs.com/Mail-maomao/p/11458935.html
總結(jié)
以上是生活随笔為你收集整理的Go 面向对象之结构体的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。