溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Go基礎(chǔ)編程之什么是結(jié)構(gòu)體

發(fā)布時(shí)間:2021-10-23 11:31:00 來(lái)源:億速云 閱讀:125 作者:iii 欄目:web開(kāi)發(fā)

本篇內(nèi)容主要講解“Go基礎(chǔ)編程之什么是結(jié)構(gòu)體”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“Go基礎(chǔ)編程之什么是結(jié)構(gòu)體”吧!

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

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

Go基礎(chǔ)編程之什么是結(jié)構(gòu)體

定義

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

type name struct{      fieldName1 type1      fieldName2 type2      ... }

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

type User struct {      Name string      age  int }

實(shí)例化

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

直接定義變量使用

package main  import (     "fmt" )  type User struct {      Name string      age  int }  func main() {      var user1 User //定義User 類(lèi)型變量user      var user2 *User //類(lèi)型指針,未分配內(nèi)存,不能直接使用      fmt.Println(user1, user2) //{ 0} <nil> }

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

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

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

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

訪問(wèn)成員

使用 . 來(lái)訪問(wèn)

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

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

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

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

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

package main  import (      "fmt"      "unsafe" )  func main() {      user1 := struct{}{}      user2 := struct{}{}      fmt.Printf("%p,%dn", &user1, unsafe.Sizeof(user1)) //0x585218,0      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)體類(lèi)型的 chan

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

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

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

比較

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

package main  import (     "fmt" )  func main() {      user1 := struct {      Name string      }{Name: "abc"}      user2 := struct {      Name string      }{Name: "abc"}      fmt.Println(user1 == user2) //true }

成員名稱(chēng)不一樣

package main  import (     "fmt" )  func main() {      user1 := struct {      Name string      }{Name: "abc"}      user2 := struct {      name string      }{name: "abc"}      fmt.Println(user1 == user2) //invalid operation: user1 == user2 (mismatched types struct { Name string } and struct { name string }) }

成員數(shù)量不一樣

package main  import (      "fmt" )  func main() {      user1 := struct {      Name string      }{Name: "abc"}      user2 := struct {      Name string      age  int      }{Name: "abc"}      fmt.Println(user1 == user2) //invalid operation: user1 == user2 (mismatched types struct { Name string } and struct { Name string; age int }) }

成員類(lèi)型不能比較

package main  import (     "fmt" )  func main() {      user1 := struct {      Name string      m    map[int]int      }{Name: "abc"}      user2 := struct {      Name string      m    map[int]int      }{Name: "abc"}      fmt.Println(user1 == user2) //invalid operation: user1 == user2 (struct containing map[int]int cannot be compared) }

順序不一樣

package main  import (      "fmt" )  func main() {      user1 := struct {      Name string      age  int      }{Name: "abc"}      user2 := struct {      age  int      Name string      }{Name: "abc"}      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è)類(lèi)型(如int),成員順序、類(lèi)型這些不一樣,整體的結(jié)構(gòu)體就不一樣,故對(duì)于強(qiáng)類(lèi)型語(yǔ)言來(lái)說(shuō)就是不能比較的,對(duì)應(yīng)類(lèi)型完全一樣還需要注意成員是否是可以比較,如slice、map等

Go語(yǔ)言沒(méi)有面向?qū)ο筮@個(gè)概念,但可以把結(jié)構(gòu)體看做是一個(gè)類(lèi),可以實(shí)現(xiàn)面向?qū)ο蟮奶匦?,如通過(guò)組合和嵌入實(shí)現(xiàn)繼承

匿名字段

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

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

package main  import (     "fmt" )  type A struct {      Name string      B } type B struct {      Age int      Name string }

訪問(wèn)成員變量

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

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

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

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

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

正確做法是

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

組合

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

package main  import (      "fmt" )  type A struct {      Btype B } type B struct {      Age int      Name string }  func main() {      var a = A{Btype:B{Name:"b",Age:20}}      fmt.Println(a.Name) //.Name undefined (type A has no field or method Name) }

標(biāo)簽

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

type User struct {  Id int `json:"id"`  Account string `json:"account" form:"account"`  Nickname string `gorm:"nickname" json:"nickname" form:"nickname"` }

方法

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

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

接收者是自定義的類(lèi)型

package main  import (     "fmt" )  type A struct {} //結(jié)構(gòu)體  type B int  //int  func (a A) show()  {     fmt.Println("a............") }  func (b B) show()  {      fmt.Println("b............") }  func main() {      var a  A      var b  B      a.show()      b.show() }

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

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

接收者 值 可以是值類(lèi)型或指針類(lèi)型

package main  import (      "fmt" )  type A struct {}  type B struct {}  func (a A) show()  { //值類(lèi)型      fmt.Println("a............") }  func (b *B) show()  { //指針類(lèi)型      fmt.Println("b............") }  func main() {      var a  A      var b  B      a.show()      b.show() }

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

func main() {      var b  B      b.show()      (&b).show() }

方法可以訪問(wèn)接收者自身的信息,如下

package main  import (     "fmt" )  type User struct {      Id int       Account string       Nickname string  }  func (u User)show()  {     fmt.Println(u.Nickname) }  func main() {      var a  = User{Nickname:"測(cè)試"}       a.show() //測(cè)試 }

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

package main  import (     "fmt" )  type User struct {      Id int      Account string      Nickname string }  func (u User)show()  {     fmt.Println(u) } func (u User)setName1()  {      u.Nickname="值類(lèi)型" }  func (u *User)setName2()  {      u.Nickname="指針類(lèi)型" }  func main() {      var a  = User{Nickname:"測(cè)試"}      a.setName1()      a.show()      a.setName2()      a.show() }

接受者 類(lèi)型 本身不能為指針

package main  import (     "fmt" )  type A int   type B *int  //變量類(lèi)型為指針  func (a A) show()  {      fmt.Println("a............") }  func (b B) show()  {  //invalid receiver type B (B is a pointer type)      fmt.Println("b............") }

到此,相信大家對(duì)“Go基礎(chǔ)編程之什么是結(jié)構(gòu)體”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢(xún),關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

go
AI