Go 面向對象之結構體

#### Go 面向對象之結構體
最近有四天沒更新公衆號,有一些事情耽誤了,生活就是這樣,總會一些事情讓人措不及防;
***山濃水淺,坐看流年***

1. Go 也支持面向對象編程(OOP) 可是它和傳統的面向對象編程仍是有一些區別,並非純粹的面向對象編程;
2. Go 中沒有類(class), Go 中struct 和其它編程語言中的類有同等地位,因此咱們能夠理解Go 是基於struct 來實現OOP;
3. Go 面向對象很簡潔,沒有傳統OOP 的繼承,方法重載,構造函數等等;
4. Go 面向對象仍有繼承,封裝,多態的特性,只是它的實現與傳統的OOP語言不一樣;
##### 結構體與結構體變量(實例/對象)的關係圖

 
---
說明:
1. 將一類事物的特性提取出來(好比貓類),造成一個新的數據類型就是一個結構體;
2. 經過這個結構體,能夠建立多個變量(實例/對象);
3. 事物能夠是貓類,也能夠是其它的類...;
案例:
package main

import "fmt"

// 定義一個結構體,相似於類
// 將Cat 的各個字段/屬性,放入到結構體中
type Cat struct {
   Name string
   Age uint
   Color string
   Hobby string
}
func main(){
   // 聲明一個Cat 變量,也就是實例
   var a1 Cat
   a1.Name = "小花"
   a1.Age = 2
   a1.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 main

import "fmt"

// 若是結構體裏的字段是引用類型的: slice map channel;
// 在使用前須要make分配內存才能使用;
type Person struct {
   Name string
   Age int
   Hobby [3]string
   ptr *string
   slice []int
   Parents map[string]string
}
type Cat struct {
   Name string
   Age int
}
func main(){
   var a1 Person
   fmt.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")
   }
   // 結構體字段是引用類型的話,使用前須要make
   a1.slice = make([]int,10)
   a1.slice[0] = 1
   a1.slice[1] = 2
   a1.slice[2] = 3
   a1.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 Cat
   var c2 Cat
   c1.Name = "c1"
   c2.Name = "c2"
   c1.Age = 1
   c2.Age = 2
   fmt.Println(c1,c2) //{c1 1} {c2 2} 
}

  


---
##### 建立結構變量和訪問結構體字段
package main

import "fmt"

type Cat struct {
   Name string
   Age int
}
func main(){
   // 方式1: 先聲明,再賦值
   var c1 Cat
   c1.Name = "c1"
   c1.Age = 1
   fmt.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 = 4
   fmt.Println(*c4)
   // 方式5: &{} 方式
   var c5 *Cat = &Cat{}
   c5.Name = "c5"
   c5.Age = 5
   fmt.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 main

import (
   "encoding/json"
   "fmt"
)

type Person struct {
   Name string
   Age int
   Hobby string
}
type Student struct {
   Name string
   Age int
   Hobby string
}
type Cat struct {
   Name string `json:"name"`
   Age int `json:"age"`
}
func main(){
   var p1 Person
   p1.Name = "p1"
   p1.Age = 22
   p1.Hobby = "run"
   // 結構體變量的地址
   fmt.Printf("p1 address: %p\n",&p1)
   fmt.Printf("p1.Name address: %p\n",&p1.Name) // 0xc0000562d0
   fmt.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 Student
   s1 = Student(p1)
   fmt.Println(s1)
   fmt.Printf("s1 type is %T\n",s1) // Student
   // struct tag
   var c1 Cat
   c1.Name = "小花"
   c1.Age = 12
   jsonStr,err := json.Marshal(c1)
   if err != nil {
      fmt.Println(err)
   }
   // 輸出的是結構體中tag 定義的名稱
   fmt.Println(string(jsonStr)) // {"name":"小花","age":12} 
}

  我的微信公衆號上有最新內容,歡迎關注交流學習編程

相關文章
相關標籤/搜索