日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

结构体怎么赋值_Go 经典入门系列 16:结构体

發布時間:2025/10/17 编程问答 16 豆豆
生活随笔 收集整理的這篇文章主要介紹了 结构体怎么赋值_Go 经典入门系列 16:结构体 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
點擊上方藍色“Go語言中文網”關注,每天一起學 Go

歡迎來到 Golang 系列教程的第 16 個教程。

什么是結構體?

結構體是用戶定義的類型,表示若干個字段(Field)的集合。有時應該把數據整合在一起,而不是讓這些數據沒有聯系。這種情況下可以使用結構體。

例如,一個職員有 firstName、lastName 和 age 三個屬性,而把這些屬性組合在一個結構體 employee 中就很合理。

結構體的聲明

type?Employee?struct?{
????firstName?string
????lastName??string
????age???????int
}

在上面的代碼片段里,聲明了一個結構體類型 Employee,它有 firstName、lastName 和 age 三個字段。通過把相同類型的字段聲明在同一行,結構體可以變得更加緊湊。在上面的結構體中,firstName 和 lastName 屬于相同的 string 類型,于是這個結構體可以重寫為:

type?Employee?struct?{
????firstName,?lastName?string
????age,?salary?????????int
}

上面的結構體 Employee 稱為 命名的結構體(Named Structure)。我們創建了名為 Employee 的新類型,而它可以用于創建 Employee 類型的結構體變量。

聲明結構體時也可以不用聲明一個新類型,這樣的結構體類型稱為 匿名結構體(Anonymous Structure)

var?employee?struct?{
????firstName,?lastName?string
????age?int
}

上述代碼片段創建一個匿名結構體 employee。

創建命名的結構體

通過下面代碼,我們定義了一個命名的結構體 Employee

package?main

import?(
????"fmt"
)

type?Employee?struct?{
????firstName,?lastName?string
????age,?salary?????????int
}

func?main()?{

????//creating?structure?using?field?names
????emp1?:=?Employee{
????????firstName:?"Sam",
????????age:???????25,
????????salary:????500,
????????lastName:??"Anderson",
????}

????//creating?structure?without?using?field?names
????emp2?:=?Employee{"Thomas",?"Paul",?29,?800}

????fmt.Println("Employee?1",?emp1)
????fmt.Println("Employee?2",?emp2)
}

在線運行程序[1]

在上述程序的第 7 行,我們創建了一個命名的結構體 Employee。而在第 15 行,通過指定每個字段名的值,我們定義了結構體變量 emp1。字段名的順序不一定要與聲明結構體類型時的順序相同。在這里,我們改變了 lastName 的位置,將其移到了末尾。這樣做也不會有任何的問題。

在上面程序的第 23 行,定義 emp2 時我們省略了字段名。在這種情況下,就需要保證字段名的順序與聲明結構體時的順序相同。

該程序將輸出:

Employee?1?{Sam?Anderson?25?500}
Employee?2?{Thomas?Paul?29?800}

創建匿名結構體

package?main

import?(
????"fmt"
)

func?main()?{
????emp3?:=?struct?{
????????firstName,?lastName?string
????????age,?salary?????????int
????}{
????????firstName:?"Andreah",
????????lastName:??"Nikola",
????????age:???????31,
????????salary:????5000,
????}

????fmt.Println("Employee?3",?emp3)
}

在線運行程序[2]

在上述程序的第 3 行,我們定義了一個匿名結構體變量 emp3。上面我們已經提到,之所以稱這種結構體是匿名的,是因為它只是創建一個新的結構體變量 em3,而沒有定義任何結構體類型。

該程序會輸出:

Employee?3?{Andreah?Nikola?31?5000}

結構體的零值(Zero Value)

當定義好的結構體并沒有被顯式地初始化時,該結構體的字段將默認賦為零值。

package?main

import?(
????"fmt"
)

type?Employee?struct?{
????firstName,?lastName?string
????age,?salary?????????int
}

func?main()?{
????var?emp4?Employee?//zero?valued?structure
????fmt.Println("Employee?4",?emp4)
}

在線運行程序[3]

該程序定義了 emp4,卻沒有初始化任何值。因此 firstName 和 lastName 賦值為 string 的零值("")。而 age 和 salary 賦值為 int 的零值(0)。該程序會輸出:

Employee?4?{?0?0}

當然還可以為某些字段指定初始值,而忽略其他字段。這樣,忽略的字段名會賦值為零值。

package?main

import?(
????"fmt"
)

type?Employee?struct?{
????firstName,?lastName?string
????age,?salary?????????int
}

func?main()?{
????emp5?:=?Employee{
????????firstName:?"John",
????????lastName:??"Paul",
????}
????fmt.Println("Employee?5",?emp5)
}

在線運行程序[4]

在上面程序中的第 14 行和第 15 行,我們初始化了 firstName 和 lastName,而 age 和 salary 沒有進行初始化。因此 age 和 salary 賦值為零值。該程序會輸出:

Employee?5?{John?Paul?0?0}

訪問結構體的字段

點號操作符 . 用于訪問結構體的字段。

package?main

import?(
????"fmt"
)

type?Employee?struct?{
????firstName,?lastName?string
????age,?salary?????????int
}

func?main()?{
????emp6?:=?Employee{"Sam",?"Anderson",?55,?6000}
????fmt.Println("First?Name:",?emp6.firstName)
????fmt.Println("Last?Name:",?emp6.lastName)
????fmt.Println("Age:",?emp6.age)
????fmt.Printf("Salary:?$%d",?emp6.salary)
}

在線運行程序[5]

上面程序中的 emp6.firstName 訪問了結構體 emp6 的字段 firstName。該程序輸出:

First?Name:?Sam
Last?Name:?Anderson
Age:?55
Salary:?$6000

還可以創建零值的 struct,以后再給各個字段賦值。

package?main

import?(
????"fmt"
)

type?Employee?struct?{
????firstName,?lastName?string
????age,?salary?????????int
}

func?main()?{
????var?emp7?Employee
????emp7.firstName?=?"Jack"
????emp7.lastName?=?"Adams"
????fmt.Println("Employee?7:",?emp7)
}

在線運行程序[6]

在上面程序中,我們定義了 emp7,接著給 firstName 和 lastName 賦值。該程序會輸出:

Employee?7:?{Jack?Adams?0?0}

結構體的指針

還可以創建指向結構體的指針。

package?main

import?(
????"fmt"
)

type?Employee?struct?{
????firstName,?lastName?string
????age,?salary?????????int
}

func?main()?{
????emp8?:=?&Employee{"Sam",?"Anderson",?55,?6000}
????fmt.Println("First?Name:",?(*emp8).firstName)
????fmt.Println("Age:",?(*emp8).age)
}

在線運行程序[7]

在上面程序中,emp8 是一個指向結構體 Employee 的指針。(*emp8).firstName 表示訪問結構體 emp8 的 firstName 字段。該程序會輸出:

First?Name:?Sam
Age:?55

Go 語言允許我們在訪問 firstName 字段時,可以使用 emp8.firstName 來代替顯式的解引用 (*emp8).firstName

package?main

import?(
????"fmt"
)

type?Employee?struct?{
????firstName,?lastName?string
????age,?salary?????????int
}

func?main()?{
????emp8?:=?&Employee{"Sam",?"Anderson",?55,?6000}
????fmt.Println("First?Name:",?emp8.firstName)
????fmt.Println("Age:",?emp8.age)
}

在線運行程序[8]

在上面的程序中,我們使用 emp8.firstName 來訪問 firstName 字段,該程序會輸出:

First?Name:?Sam
Age:?55

匿名字段

當我們創建結構體時,字段可以只有類型,而沒有字段名。這樣的字段稱為匿名字段(Anonymous Field)。

以下代碼創建一個 Person 結構體,它含有兩個匿名字段 string 和 int。

type?Person?struct?{
????string
????int
}

我們接下來使用匿名字段來編寫一個程序。

package?main

import?(
????"fmt"
)

type?Person?struct?{
????string
????int
}

func?main()?{
????p?:=?Person{"Naveen",?50}
????fmt.Println(p)
}

在線運行程序[9]

在上面的程序中,結構體 Person 有兩個匿名字段。p := Person{"Naveen", 50} 定義了一個 Person 類型的變量。該程序輸出 {Naveen 50}。

雖然匿名字段沒有名稱,但其實匿名字段的名稱就默認為它的類型。比如在上面的 Person 結構體里,雖說字段是匿名的,但 Go 默認這些字段名是它們各自的類型。所以 Person 結構體有兩個名為 string 和 int 的字段。

package?main

import?(
????"fmt"
)

type?Person?struct?{
????string
????int
}

func?main()?{
????var?p1?Person
????p1.string?=?"naveen"
????p1.int?=?50
????fmt.Println(p1)
}

在線運行程序[10]

在上面程序的第 14 行和第 15 行,我們訪問了 Person 結構體的匿名字段,我們把字段類型作為字段名,分別為 "string" 和 "int"。上面程序的輸出如下:

{naveen?50}

嵌套結構體(Nested Structs)

結構體的字段有可能也是一個結構體。這樣的結構體稱為嵌套結構體。

package?main

import?(
????"fmt"
)

type?Address?struct?{
????city,?state?string
}
type?Person?struct?{
????name?string
????age?int
????address?Address
}

func?main()?{
????var?p?Person
????p.name?=?"Naveen"
????p.age?=?50
????p.address?=?Address?{
????????city:?"Chicago",
????????state:?"Illinois",
????}
????fmt.Println("Name:",?p.name)
????fmt.Println("Age:",p.age)
????fmt.Println("City:",p.address.city)
????fmt.Println("State:",p.address.state)
}

在線運行程序[11]

上面的結構體 Person 有一個字段 address,而 address 也是結構體。該程序輸出:

Name:?Naveen
Age:?50
City:?Chicago
State:?Illinois

提升字段(Promoted Fields)

如果是結構體中有匿名的結構體類型字段,則該匿名結構體里的字段就稱為提升字段。這是因為提升字段就像是屬于外部結構體一樣,可以用外部結構體直接訪問。我知道這種定義很復雜,所以我們直接研究下代碼來理解吧。

type?Address?struct?{
????city,?state?string
}
type?Person?struct?{
????name?string
????age??int
????Address
}

在上面的代碼片段中,Person 結構體有一個匿名字段 Address,而 Address 是一個結構體。現在結構體 Address 有 city 和 state 兩個字段,訪問這兩個字段就像在 Person 里直接聲明的一樣,因此我們稱之為提升字段。

package?main

import?(
????"fmt"
)

type?Address?struct?{
????city,?state?string
}
type?Person?struct?{
????name?string
????age??int
????Address
}

func?main()?{
????var?p?Person
????p.name?=?"Naveen"
????p.age?=?50
????p.Address?=?Address{
????????city:??"Chicago",
????????state:?"Illinois",
????}
????fmt.Println("Name:",?p.name)
????fmt.Println("Age:",?p.age)
????fmt.Println("City:",?p.city)?//city?is?promoted?field
????fmt.Println("State:",?p.state)?//state?is?promoted?field
}

在線運行程序[12]

在上面代碼中的第 26 行和第 27 行,我們使用了語法 p.city 和 p.state,訪問提升字段 city 和 state 就像它們是在結構體 p 中聲明的一樣。該程序會輸出:

Name:?Naveen
Age:?50
City:?Chicago
State:?Illinois

導出結構體和字段

如果結構體名稱以大寫字母開頭,則它是其他包可以訪問的導出類型(Exported Type)。同樣,如果結構體里的字段首字母大寫,它也能被其他包訪問到。

讓我們使用自定義包,編寫一個程序來更好地去理解它。

在你的 Go 工作區的 src 目錄中,創建一個名為 structs 的文件夾。另外在 structs 中再創建一個目錄 computer。

在 computer 目錄中,在名為 spec.go 的文件中保存下面的程序。

package?computer

type?Spec?struct?{?//exported?struct
????Maker?string?//exported?field
????model?string?//unexported?field
????Price?int?//exported?field
}

上面的代碼片段中,創建了一個 computer 包,里面有一個導出結構體類型 Spec。Spec 有兩個導出字段 Maker 和 Price,和一個未導出的字段 model。接下來我們會在 main 包中導入這個包,并使用 Spec 結構體。

package?main

import?"structs/computer"
import?"fmt"

func?main()?{
????var?spec?computer.Spec
????spec.Maker?=?"apple"
????spec.Price?=?50000
????fmt.Println("Spec:",?spec)
}

包結構如下所示:

src
???structs
????????computer
????????????spec.go
????????main.go

在上述程序的第 3 行,我們導入了 computer 包。在第 8 行和第 9 行,我們訪問了結構體 Spec 的兩個導出字段 Maker 和 Price。執行命令 go install structs 和 workspacepath/bin/structs,運行該程序。

如果我們試圖訪問未導出的字段 model,編譯器會報錯。將 main.go 的內容替換為下面的代碼。

package?main

import?"structs/computer"
import?"fmt"

func?main()?{
????var?spec?computer.Spec
????spec.Maker?=?"apple"
????spec.Price?=?50000
????spec.model?=?"Mac?Mini"
????fmt.Println("Spec:",?spec)
}

在上面程序的第 10 行,我們試圖訪問未導出的字段 model。如果運行這個程序,編譯器會產生錯誤:spec.model undefined (cannot refer to unexported field or method model)

結構體相等性(Structs Equality)

結構體是值類型。如果它的每一個字段都是可比較的,則該結構體也是可比較的。如果兩個結構體變量的對應字段相等,則這兩個變量也是相等的

package?main

import?(
????"fmt"
)

type?name?struct?{
????firstName?string
????lastName?string
}


func?main()?{
????name1?:=?name{"Steve",?"Jobs"}
????name2?:=?name{"Steve",?"Jobs"}
????if?name1?==?name2?{
????????fmt.Println("name1?and?name2?are?equal")
????}?else?{
????????fmt.Println("name1?and?name2?are?not?equal")
????}

????name3?:=?name{firstName:"Steve",?lastName:"Jobs"}
????name4?:=?name{}
????name4.firstName?=?"Steve"
????if?name3?==?name4?{
????????fmt.Println("name3?and?name4?are?equal")
????}?else?{
????????fmt.Println("name3?and?name4?are?not?equal")
????}
}

在線運行程序[13]

在上面的代碼中,結構體類型 name 包含兩個 string 類型。由于字符串是可比較的,因此可以比較兩個 name 類型的結構體變量。

上面代碼中 name1 和 name2 相等,而 name3 和 name4 不相等。該程序會輸出:

name1?and?name2?are?equal
name3?and?name4?are?not?equal

如果結構體包含不可比較的字段,則結構體變量也不可比較。

package?main

import?(
????"fmt"
)

type?image?struct?{
????data?map[int]int
}

func?main()?{
????image1?:=?image{data:?map[int]int{
????????0:?155,
????}}
????image2?:=?image{data:?map[int]int{
????????0:?155,
????}}
????if?image1?==?image2?{
????????fmt.Println("image1?and?image2?are?equal")
????}
}

在線運行程序[14]

在上面代碼中,結構體類型 image 包含一個 map 類型的字段。由于 map 類型是不可比較的,因此 image1 和 image2 也不可比較。如果運行該程序,編譯器會報錯:main.go:18: invalid operation: image1 == image2 (struct containing map[int]int cannot be compared)

github[15] 上有本教程的源代碼。

上一教程 - 指針

下一教程 - 方法[16]



推薦閱讀

  • Go 經典入門系列 15:指針

福利我為大家整理了一份從入門到進階的Go學習資料禮包,包含學習建議:入門看什么,進階看什么。關注公眾號 「polarisxu」,回復 ebook獲取;還可以回復「進群」,和數萬 Gopher 交流學習。

總結

以上是生活随笔為你收集整理的结构体怎么赋值_Go 经典入门系列 16:结构体的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。