日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Go基礎(chǔ)編程:結(jié)構(gòu)體

結(jié)構(gòu)體(struct)是自定義方式形成新的數(shù)據(jù)類型,結(jié)構(gòu)體是類型中帶有成員的復(fù)合類型。Go 語言結(jié)構(gòu)體是一種聚合的數(shù)據(jù)類型,是由零個(gè)或多個(gè)任意類型的值聚合成的實(shí)體。每個(gè)值稱為結(jié)構(gòu)體的成員。來描述真實(shí)世界的實(shí)體和實(shí)體對(duì)應(yīng)的各種屬性。

結(jié)構(gòu)體屬性也叫 字段 或 成員 ,每個(gè)字段都有名稱和類型,每個(gè)名稱是唯一的??梢允侨魏晤愋?,如普通類型、復(fù)合類型、函數(shù)、map、interface、struct等,所以我們可以理解為go語言中的“類”。

定義

結(jié)構(gòu)體定義方式如下:

 
 
 
 
  1. type name struct{ 
  2.      fieldName1 type1 
  3.      fieldName2 type2 
  4.      ... 

如下,定義User 結(jié)構(gòu)體:

 
 
 
 
  1. type User struct { 
  2.      Name string 
  3.      age  int 

實(shí)例化

上面定義只是類型,就想是一個(gè) int 一樣,需要定義一個(gè)類型變量才可以使用,類似Java的類。

直接定義變量使用

 
 
 
 
  1. package main 
  2. import ( 
  3.     "fmt" 
  4. type User struct { 
  5.      Name string 
  6.      age  int 
  7. func main() { 
  8.      var user1 User //定義User 類型變量user 
  9.      var user2 *User //類型指針,未分配內(nèi)存,不能直接使用 
  10.      fmt.Println(user1, user2) //{ 0}  

定義默認(rèn)成員變量

 
 
 
 
  1. var user1 = User{Name: "abc"} 
  2. fmt.Println(user1) 
  3.  
  4. func NewUser() *User { 
  5.     return &User{Name:"abc",age:20} 

使用內(nèi)建函數(shù) new() 分配內(nèi)存返回類型變量指針

 
 
 
 
  1. var user = new(User) 
  2. fmt.Println(user) //&{ 0} 

訪問成員

使用 . 來訪問

 
 
 
 
  1. var user User 
  2. user.Name = "abc" 
  3. user.age = 20 
  4. fmt.Println(user) //{abc 20} 

首字母大小寫問題,成員大寫表示包外可見(即面向?qū)ο蟮墓袑傩?,小寫包外不可見

零值:結(jié)構(gòu)體的零值是 nil

初始值:結(jié)構(gòu)體的初始值是非 nil 時(shí),各成員對(duì)應(yīng)類型的初始值

空結(jié)構(gòu)體:空結(jié)構(gòu)體就是沒有字段的結(jié)構(gòu)體,空結(jié)構(gòu)體不占內(nèi)存

 
 
 
 
  1. package main 
  2. import ( 
  3.      "fmt" 
  4.      "unsafe" 
  5. func main() { 
  6.      user1 := struct{}{} 
  7.      user2 := struct{}{} 
  8.      fmt.Printf("%p,%dn", &user1, unsafe.Sizeof(user1)) //0x585218,0 
  9.      fmt.Printf("%p,%dn", &user2, unsafe.Sizeof(user2)) //0x585218,0 

從上面可以看出空結(jié)構(gòu)體內(nèi)存地址和大小都是一樣的。根據(jù)這個(gè)特性,使用空結(jié)構(gòu)體可以作為信號(hào)量,起到信號(hào)作用但不占內(nèi)存。如空結(jié)構(gòu)體類型的 chan

匿名結(jié)構(gòu)體

匿名結(jié)構(gòu)體沒有類型名稱,無須通過 type 關(guān)鍵字定義就可以直接使用。

 
 
 
 
  1. user := struct { 
  2.      Name string 
  3.  }{Name: "abc"} 
  4. fmt.Println(user) //{abc} 

比較

如果結(jié)構(gòu)體的全部成員都是 可以比較 的,且成員的 順序 、 類型 、 數(shù)量 完全一樣才可以比較,兩個(gè)結(jié)構(gòu)體將可以使用==或!=運(yùn)算符進(jìn)行比較。

 
 
 
 
  1. package main 
  2. import ( 
  3.     "fmt" 
  4. func main() { 
  5.      user1 := struct { 
  6.      Name string 
  7.      }{Name: "abc"} 
  8.      user2 := struct { 
  9.      Name string 
  10.      }{Name: "abc"} 
  11.      fmt.Println(user1 == user2) //true 

成員名稱不一樣

 
 
 
 
  1. package main 
  2. import ( 
  3.     "fmt" 
  4. func main() { 
  5.      user1 := struct { 
  6.      Name string 
  7.      }{Name: "abc"} 
  8.      user2 := struct { 
  9.      name string 
  10.      }{name: "abc"} 
  11.      fmt.Println(user1 == user2) //invalid operation: user1 == user2 (mismatched types struct { Name string } and struct { name string }) 

成員數(shù)量不一樣

 
 
 
 
  1. package main 
  2. import ( 
  3.      "fmt" 
  4. func main() { 
  5.      user1 := struct { 
  6.      Name string 
  7.      }{Name: "abc"} 
  8.      user2 := struct { 
  9.      Name string 
  10.      age  int 
  11.      }{Name: "abc"} 
  12.      fmt.Println(user1 == user2) //invalid operation: user1 == user2 (mismatched types struct { Name string } and struct { Name string; age int }) 

成員類型不能比較

 
 
 
 
  1. package main 
  2. import ( 
  3.     "fmt" 
  4. func main() { 
  5.      user1 := struct { 
  6.      Name string 
  7.      m    map[int]int 
  8.      }{Name: "abc"} 
  9.      user2 := struct { 
  10.      Name string 
  11.      m    map[int]int 
  12.      }{Name: "abc"} 
  13.      fmt.Println(user1 == user2) //invalid operation: user1 == user2 (struct containing map[int]int cannot be compared) 

順序不一樣

 
 
 
 
  1. package main 
  2. import ( 
  3.      "fmt" 
  4. func main() { 
  5.      user1 := struct { 
  6.      Name string 
  7.      age  int 
  8.      }{Name: "abc"} 
  9.      user2 := struct { 
  10.      age  int 
  11.      Name string 
  12.      }{Name: "abc"} 
  13.      fmt.Println(user1 == user2) //invalid operation: user1 == user2 (mismatched types struct { Name string; age int } and struct { age int; Name string }) 

其實(shí)整個(gè)結(jié)構(gòu)體就是一個(gè)類型(如int),成員順序、類型這些不一樣,整體的結(jié)構(gòu)體就不一樣,故對(duì)于強(qiáng)類型語言來說就是不能比較的,對(duì)應(yīng)類型完全一樣還需要注意成員是否是可以比較,如slice、map等

Go語言沒有面向?qū)ο筮@個(gè)概念,但可以把結(jié)構(gòu)體看做是一個(gè)類,可以實(shí)現(xiàn)面向?qū)ο蟮奶匦裕缤ㄟ^組合和嵌入實(shí)現(xiàn)繼承

匿名字段

匿名字段是結(jié)構(gòu)體沒有顯示的名字,是結(jié)構(gòu)體嵌入一個(gè)或多個(gè)結(jié)構(gòu)體,如下面

B直接嵌入A ,B是匿名字段

 
 
 
 
  1. package main 
  2. import ( 
  3.     "fmt" 
  4. type A struct { 
  5.      Name string 
  6.      B 
  7. type B struct { 
  8.      Age int 
  9.      Name string 

訪問成員變量

 
 
 
 
  1. func main() { 
  2.      var a = A{Name:"a",B:B{Name:"b",Age:20}} 
  3.      fmt.Printf("%#vn", a) //main.A{Name:"", B:main.B{Age:0}} 
  4.      fmt.Println(a.Name)  //a 
  5.      fmt.Println(a.B.Name)  //b 
  6.      fmt.Println(a.Age)  //20  

只有一個(gè)成員名稱的情況下,Go語法糖可以省略嵌入結(jié)構(gòu)體

 
 
 
 
  1. fmt.Println(a.B.Age) //20 
  2. fmt.Println(a.Age)   //20 

對(duì)應(yīng)有多個(gè)相同名稱的成員,不能省略,因?yàn)榫幾g器不知道是哪個(gè)

 
 
 
 
  1. type C struct { 
  2.      A 
  3.      B 
  4. func main() { 
  5.      var c = C{A:A{Name:"a"},B:B{Name:"b",Age:20}} 
  6.      fmt.Println(c.Name) //ambiguous selector c.Name 

正確做法是

 
 
 
 
  1. func main() { 
  2.      var c = C{A:A{Name:"a"},B:B{Name:"b",Age:20}} 
  3.      fmt.Println(c.A.Name) //a 
  4.      fmt.Println(c.B.Name) //b 

組合

上面是沒有名字的嵌入結(jié)構(gòu)體,還可以給嵌入結(jié)構(gòu)體命名,訪問必須要帶上具體的字段,不能省略。

 
 
 
 
  1. package main 
  2. import ( 
  3.      "fmt" 
  4. type A struct { 
  5.      Btype B 
  6. type B struct { 
  7.      Age int 
  8.      Name string 
  9. func main() { 
  10.      var a = A{Btype:B{Name:"b",Age:20}} 
  11.      fmt.Println(a.Name) //.Name undefined (type A has no field or method Name) 

標(biāo)簽

如下面在字段后面用 `` 包起來的是標(biāo)簽,主要是通過反射來序列化和反序列化,具體由反射章節(jié)來講。

 
 
 
 
  1. type User struct { 
  2.  Id int `json:"id"` 
  3.  Account string `json:"account" form:"account"` 
  4.  Nickname string `gorm:"nickname" json:"nickname" form:"nickname"` 

方法

方法一般都是面向?qū)ο缶幊?OOP)的一個(gè)特性,Go語言的方法其實(shí)與一個(gè)值或變量關(guān)聯(lián)的特殊的函數(shù)。這個(gè)值或變量叫做 接收者

 
 
 
 
  1. func ([typeName] 接收者) name (param) [return]{} 

接收者是自定義的類型

 
 
 
 
  1. package main 
  2. import ( 
  3.     "fmt" 
  4. type A struct {} //結(jié)構(gòu)體 
  5. type B int  //int 
  6. func (a A) show()  { 
  7.     fmt.Println("a............") 
  8. func (b B) show()  { 
  9.      fmt.Println("b............") 
  10. func main() { 
  11.      var a  A 
  12.      var b  B 
  13.      a.show() 
  14.      b.show() 

接收者不能直接用內(nèi)置類型

 
 
 
 
  1. func (c int) show()  {  //cannot define new methods on non-local type int 
  2.     fmt.Println("b............") 

接收者 值 可以是值類型或指針類型

 
 
 
 
  1. package main 
  2. import ( 
  3.      "fmt" 
  4. type A struct {} 
  5. type B struct {} 
  6. func (a A) show()  { //值類型 
  7.      fmt.Println("a............") 
  8. func (b *B) show()  { //指針類型 
  9.      fmt.Println("b............") 
  10. func main() { 
  11.      var a  A 
  12.      var b  B 
  13.      a.show() 
  14.      b.show() 

對(duì)與 B 來說,下面兩種調(diào)用方式是等價(jià)的,本質(zhì)上他們都是一樣的, b.show() 的寫法是省略了 (&b) ,只不過由語法糖來補(bǔ)全

 
 
 
 
  1. func main() { 
  2.      var b  B 
  3.      b.show() 
  4.      (&b).show() 

方法可以訪問接收者自身的信息,如下

 
 
 
 
  1. package main 
  2. import ( 
  3.     "fmt" 
  4. type User struct { 
  5.      Id int  
  6.      Account string  
  7.      Nickname string  
  8. func (u User)show()  { 
  9.     fmt.Println(u.Nickname) 
  10. func main() { 
  11.      var a  = User{Nickname:"測(cè)試"}  
  12.      a.show() //測(cè)試 

值類型接收者拷貝類型的全部,修改 不會(huì) 影響原數(shù)據(jù);指針拷貝的是地址,修改 會(huì) 影響原數(shù)據(jù)

 
 
 
 
  1. package main 
  2. import ( 
  3.     "fmt" 
  4. type User struct { 
  5.      Id int 
  6.      Account string 
  7.      Nickname string 
  8. func (u User)show()  { 
  9.     fmt.Println(u) 
  10. func (u User)setName1()  { 
  11.      u.Nickname="值類型" 
  12. func (u *User)setName2()  { 
  13.      u.Nickname="指針類型" 
  14. func main() { 
  15.      var a  = User{Nickname:"測(cè)試"} 
  16.      a.setName1() 
  17.      a.show() 
  18.      a.setName2() 
  19.      a.show() 

接受者 類型 本身不能為指針

 
 
 
 
  1. package main 
  2. import ( 
  3.     "fmt" 
  4. type A int  
  5. type B *int  //變量類型為指針 
  6. func (a A) show()  { 
  7.      fmt.Println("a............") 
  8. func (b B) show()  {  //invalid receiver type B (B is a pointer type) 
  9.      fmt.Println("b............") 

本文標(biāo)題:Go基礎(chǔ)編程:結(jié)構(gòu)體
分享網(wǎng)址:http://www.dlmjj.cn/article/cooepih.html