Go 面向对象之结构体
生活随笔
收集整理的這篇文章主要介紹了
Go 面向对象之结构体
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
#### Go 面向對象之結構體
最近有四天沒更新公眾號,有一些事情耽誤了,生活就是這樣,總會一些事情讓人措不及防;
***山濃水淺,坐看流年***
1. Go 也支持面向對象編程(OOP) 但是它和傳統的面向對象編程還是有一些區別,并不是純粹的面向對象編程;
2. Go 中沒有類(class), Go 中struct 和其它編程語言中的類有同等地位,所以我們可以理解Go 是基于struct 來實現OOP;
3. Go 面向對象很簡潔,沒有傳統OOP 的繼承,方法重載,構造函數等等;
4. Go 面向對象仍有繼承,封裝,多態的特性,只是它的實現與傳統的OOP語言不同;
##### 結構體與結構體變量(實例/對象)的關系圖
---
說明:
1. 將一類事物的特性提取出來(比如貓類),形成一個新的數據類型就是一個結構體;
2. 通過這個結構體,可以創建多個變量(實例/對象);
3. 事物可以是貓類,也可以是其它的類...;
案例: package mainimport "fmt"// 定義一個結構體,類似于類 // 將Cat 的各個字段/屬性,放入到結構體中 type Cat struct {Name stringAge uintColor stringHobby string } func main(){// 聲明一個Cat 變量,也就是實例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) }
---
結構體與結構體變量(實例)的區別
1. 結構體是自定義的數據類型,代表一類事物;
2. 結構體變量是具體的,實際的,代表一個具體的變量;
---
##### 結構體變量在內存中的布局
##### 如何聲明結構體
基本語法:
type 結構體名稱 struct {
field1 type
field2 type
...
}
例如:
typt Person struct {
Name string
Age int
Class string
}
##### 字段屬性
字段是結構體的組成部分,一般是基本數據類型,數組,同時也可以是引用類型;
注意事項:
1. 字段聲明語法同變量一樣: 字段名 字段類型
2. 在創建一個結構體變量后,如果沒有給字段賦值,每個字段都對應一個默認值,引用類型默認值為nil;
3. 不同結構體變量的字段是獨立的,互不影響: 結構體是值類型; package mainimport "fmt"// 如果結構體里的字段是引用類型的: slice map channel; // 在使用前需要make分配內存才能使用; 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")}// 結構體字段是引用類型的話,使用前需要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]}// 不同結構體變量間互不影響var c1 Catvar c2 Catc1.Name = "c1"c2.Name = "c2"c1.Age = 1c2.Age = 2fmt.Println(c1,c2) //{c1 1} {c2 2} }
---
##### 創建結構變量和訪問結構體字段 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: 類型推導方式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 返回的都是結構體的指針類型 }
1. 第4,5 種方式返回的是***結構體指針***;
2. 結構體指針訪問字段的標準方式應該是:(*結構體指針).字段名, 如:(*c4).Name = "c4";
3. Go 做了簡化,支持***結構體指針.字段名***,如:c4.Name = "c4",Go 編譯器底層自動處理了;
---
##### 結構體使用注意事項
1. 結構體中所有的字段在內存中是連續的;
2. 結構體是用戶自定義的類型,在和其它類型轉換時需要有完全相同的字段(名稱,個數,類型);
3. 結構體進行type 定義,Go 認為是新的數據類型,可以和基本數據類型進行強轉;
4. 結構體每個字段上可以寫tag,tag 可以通過反射機制獲取,常用的場景是序列化和反序列化; 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"// 結構體變量的地址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 , 一個string 是16 字節fmt.Printf("p1.Hobby address: %p\n",&p1.Hobby)//0xc0000562e8 , 一個int 在64 位系統中為8字節// 類型之間強轉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)}// 輸出的是結構體中tag 定義的名稱fmt.Println(string(jsonStr)) // {"name":"小花","age":12} }
最近有四天沒更新公眾號,有一些事情耽誤了,生活就是這樣,總會一些事情讓人措不及防;
***山濃水淺,坐看流年***
1. Go 也支持面向對象編程(OOP) 但是它和傳統的面向對象編程還是有一些區別,并不是純粹的面向對象編程;
2. Go 中沒有類(class), Go 中struct 和其它編程語言中的類有同等地位,所以我們可以理解Go 是基于struct 來實現OOP;
3. Go 面向對象很簡潔,沒有傳統OOP 的繼承,方法重載,構造函數等等;
4. Go 面向對象仍有繼承,封裝,多態的特性,只是它的實現與傳統的OOP語言不同;
##### 結構體與結構體變量(實例/對象)的關系圖
---
說明:
1. 將一類事物的特性提取出來(比如貓類),形成一個新的數據類型就是一個結構體;
2. 通過這個結構體,可以創建多個變量(實例/對象);
3. 事物可以是貓類,也可以是其它的類...;
案例: package mainimport "fmt"// 定義一個結構體,類似于類 // 將Cat 的各個字段/屬性,放入到結構體中 type Cat struct {Name stringAge uintColor stringHobby string } func main(){// 聲明一個Cat 變量,也就是實例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) }
---
結構體與結構體變量(實例)的區別
1. 結構體是自定義的數據類型,代表一類事物;
2. 結構體變量是具體的,實際的,代表一個具體的變量;
---
##### 結構體變量在內存中的布局
##### 如何聲明結構體
基本語法:
type 結構體名稱 struct {
field1 type
field2 type
...
}
例如:
typt Person struct {
Name string
Age int
Class string
}
##### 字段屬性
字段是結構體的組成部分,一般是基本數據類型,數組,同時也可以是引用類型;
注意事項:
1. 字段聲明語法同變量一樣: 字段名 字段類型
2. 在創建一個結構體變量后,如果沒有給字段賦值,每個字段都對應一個默認值,引用類型默認值為nil;
3. 不同結構體變量的字段是獨立的,互不影響: 結構體是值類型; package mainimport "fmt"// 如果結構體里的字段是引用類型的: slice map channel; // 在使用前需要make分配內存才能使用; 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")}// 結構體字段是引用類型的話,使用前需要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]}// 不同結構體變量間互不影響var c1 Catvar c2 Catc1.Name = "c1"c2.Name = "c2"c1.Age = 1c2.Age = 2fmt.Println(c1,c2) //{c1 1} {c2 2} }
---
##### 創建結構變量和訪問結構體字段 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: 類型推導方式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 返回的都是結構體的指針類型 }
1. 第4,5 種方式返回的是***結構體指針***;
2. 結構體指針訪問字段的標準方式應該是:(*結構體指針).字段名, 如:(*c4).Name = "c4";
3. Go 做了簡化,支持***結構體指針.字段名***,如:c4.Name = "c4",Go 編譯器底層自動處理了;
---
##### 結構體使用注意事項
1. 結構體中所有的字段在內存中是連續的;
2. 結構體是用戶自定義的類型,在和其它類型轉換時需要有完全相同的字段(名稱,個數,類型);
3. 結構體進行type 定義,Go 認為是新的數據類型,可以和基本數據類型進行強轉;
4. 結構體每個字段上可以寫tag,tag 可以通過反射機制獲取,常用的場景是序列化和反序列化; 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"// 結構體變量的地址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 , 一個string 是16 字節fmt.Printf("p1.Hobby address: %p\n",&p1.Hobby)//0xc0000562e8 , 一個int 在64 位系統中為8字節// 類型之間強轉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)}// 輸出的是結構體中tag 定義的名稱fmt.Println(string(jsonStr)) // {"name":"小花","age":12} }
個人微信公眾號上有最新內容,歡迎關注交流學習
轉載于:https://www.cnblogs.com/Mail-maomao/p/11458935.html
總結
以上是生活随笔為你收集整理的Go 面向对象之结构体的全部內容,希望文章能夠幫你解決所遇到的問題。