日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 >

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

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

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

什么是結(jié)構(gòu)體?

結(jié)構(gòu)體是用戶定義的類型,表示若干個字段(Field)的集合。有時應(yīng)該把數(shù)據(jù)整合在一起,而不是讓這些數(shù)據(jù)沒有聯(lián)系。這種情況下可以使用結(jié)構(gòu)體。

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

結(jié)構(gòu)體的聲明

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

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

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

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

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

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

上述代碼片段創(chuàng)建一個匿名結(jié)構(gòu)體 employee。

創(chuàng)建命名的結(jié)構(gòu)體

通過下面代碼,我們定義了一個命名的結(jié)構(gòu)體 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 行,我們創(chuàng)建了一個命名的結(jié)構(gòu)體 Employee。而在第 15 行,通過指定每個字段名的值,我們定義了結(jié)構(gòu)體變量 emp1。字段名的順序不一定要與聲明結(jié)構(gòu)體類型時的順序相同。在這里,我們改變了 lastName 的位置,將其移到了末尾。這樣做也不會有任何的問題。

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

該程序?qū)⑤敵?#xff1a;

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

創(chuàng)建匿名結(jié)構(gòu)體

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 行,我們定義了一個匿名結(jié)構(gòu)體變量 emp3。上面我們已經(jīng)提到,之所以稱這種結(jié)構(gòu)體是匿名的,是因為它只是創(chuàng)建一個新的結(jié)構(gòu)體變量 em3,而沒有定義任何結(jié)構(gòu)體類型。

該程序會輸出:

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

結(jié)構(gòu)體的零值(Zero Value)

當(dāng)定義好的結(jié)構(gòu)體并沒有被顯式地初始化時,該結(jié)構(gòu)體的字段將默認(rèn)賦為零值。

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}

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

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 沒有進(jìn)行初始化。因此 age 和 salary 賦值為零值。該程序會輸出:

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

訪問結(jié)構(gòu)體的字段

點號操作符 . 用于訪問結(jié)構(gòu)體的字段。

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 訪問了結(jié)構(gòu)體 emp6 的字段 firstName。該程序輸出:

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

還可以創(chuàng)建零值的 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}

結(jié)構(gòu)體的指針

還可以創(chuàng)建指向結(jié)構(gòu)體的指針。

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 是一個指向結(jié)構(gòu)體 Employee 的指針。(*emp8).firstName 表示訪問結(jié)構(gòu)體 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

匿名字段

當(dāng)我們創(chuàng)建結(jié)構(gòu)體時,字段可以只有類型,而沒有字段名。這樣的字段稱為匿名字段(Anonymous Field)。

以下代碼創(chuàng)建一個 Person 結(jié)構(gòu)體,它含有兩個匿名字段 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]

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

雖然匿名字段沒有名稱,但其實匿名字段的名稱就默認(rèn)為它的類型。比如在上面的 Person 結(jié)構(gòu)體里,雖說字段是匿名的,但 Go 默認(rèn)這些字段名是它們各自的類型。所以 Person 結(jié)構(gòu)體有兩個名為 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 結(jié)構(gòu)體的匿名字段,我們把字段類型作為字段名,分別為 "string" 和 "int"。上面程序的輸出如下:

{naveen?50}

嵌套結(jié)構(gòu)體(Nested Structs)

結(jié)構(gòu)體的字段有可能也是一個結(jié)構(gòu)體。這樣的結(jié)構(gòu)體稱為嵌套結(jié)構(gòu)體。

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]

上面的結(jié)構(gòu)體 Person 有一個字段 address,而 address 也是結(jié)構(gòu)體。該程序輸出:

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

提升字段(Promoted Fields)

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

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

在上面的代碼片段中,Person 結(jié)構(gòu)體有一個匿名字段 Address,而 Address 是一個結(jié)構(gòu)體。現(xiàn)在結(jié)構(gòu)體 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 就像它們是在結(jié)構(gòu)體 p 中聲明的一樣。該程序會輸出:

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

導(dǎo)出結(jié)構(gòu)體和字段

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

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

在你的 Go 工作區(qū)的 src 目錄中,創(chuàng)建一個名為 structs 的文件夾。另外在 structs 中再創(chuàng)建一個目錄 computer。

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

package?computer

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

上面的代碼片段中,創(chuàng)建了一個 computer 包,里面有一個導(dǎo)出結(jié)構(gòu)體類型 Spec。Spec 有兩個導(dǎo)出字段 Maker 和 Price,和一個未導(dǎo)出的字段 model。接下來我們會在 main 包中導(dǎo)入這個包,并使用 Spec 結(jié)構(gòu)體。

package?main

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

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

包結(jié)構(gòu)如下所示:

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

在上述程序的第 3 行,我們導(dǎo)入了 computer 包。在第 8 行和第 9 行,我們訪問了結(jié)構(gòu)體 Spec 的兩個導(dǎo)出字段 Maker 和 Price。執(zhí)行命令 go install structs 和 workspacepath/bin/structs,運行該程序。

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

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 行,我們試圖訪問未導(dǎo)出的字段 model。如果運行這個程序,編譯器會產(chǎn)生錯誤:spec.model undefined (cannot refer to unexported field or method model)。

結(jié)構(gòu)體相等性(Structs Equality)

結(jié)構(gòu)體是值類型。如果它的每一個字段都是可比較的,則該結(jié)構(gòu)體也是可比較的。如果兩個結(jié)構(gòu)體變量的對應(yīng)字段相等,則這兩個變量也是相等的。

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]

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

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

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

如果結(jié)構(gòu)體包含不可比較的字段,則結(jié)構(gòu)體變量也不可比較。

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]

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

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

上一教程 - 指針

下一教程 - 方法[16]



推薦閱讀

  • Go 經(jīng)典入門系列 15:指針

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

總結(jié)

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

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。