結(jié)構(gòu)體
結(jié)構(gòu)體(struct)是用戶自定義的類型变擒,代表若干字段的集合随静。有時(shí)將多個(gè)數(shù)據(jù)看做一個(gè)整體要比單獨(dú)使用這些數(shù)據(jù)更有意義囚企,在這種情況下就適合使用結(jié)構(gòu)體。
比如將一個(gè)員工的 firstName, lastName 和 age 打包在一起成為一個(gè)結(jié)構(gòu)體就是很有意義的馍惹。
具名結(jié)構(gòu)體
type Employee struct {
firstName, lastName string
age int
}
上面的 Employee 是一個(gè)具名結(jié)構(gòu)體(named structure)躺率,因?yàn)樗鼊?chuàng)建了一個(gè)具有名字的結(jié)構(gòu)體類型: Employee 。
匿名結(jié)構(gòu)體
我們也可以定義一個(gè)沒有類型名稱的結(jié)構(gòu)體万矾,這種結(jié)構(gòu)體叫做匿名結(jié)構(gòu)體(anonymous structures)悼吱。
var employee struct {
firstName, lastName string
age int
}
上面的代碼片段聲明了一個(gè)匿名結(jié)構(gòu)體變量 employee。
package main
import (
"fmt"
)
func main() {
var emp1 struct {
firstName, lastName string
age int
}
emp1.firstName = "Andreah"
emp1.lastName = "Nikola"
emp1.age = 31
emp2 := struct {
firstName, lastName string
age int
}{
firstName: "Andreah",
lastName: "Nikola",
age: 31,
}
fmt.Println("Employee 1", emp1)
fmt.Println("Employee 2", emp2)
}
匿名字段
定義結(jié)構(gòu)體類型時(shí)可以僅指定字段類型而不指定字段名字良狈。這種字段叫做匿名字段(anonymous field)后添。
package main
import (
"fmt"
)
type Person struct {
string
int
}
func main() {
p := Person{"Naveen", 50}
fmt.Println(p)
}
在上面的程序中,Person 是一個(gè)具有兩個(gè)匿名字段的結(jié)構(gòu)體類型们颜,類型分別為 string
和 int
吕朵。
雖然匿名字段沒有名字,但是匿名字段的默認(rèn)名字為類型名窥突。比如上面的 Person 類型,盡管它的字段是匿名的硫嘶,但是默認(rèn)它們擁有它們的類型的名字阻问。因此 Person 結(jié)構(gòu)體有兩個(gè)名為 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)
}
在上面的程序中沦疾,我們通過使用匿名字段的類型名("string"
和 "int"
)來訪問 Person 結(jié)構(gòu)體的字段称近。
導(dǎo)出結(jié)構(gòu)體和字段
如果一個(gè)結(jié)構(gòu)體類型的名稱以大寫字母開頭,則該結(jié)構(gòu)體被導(dǎo)出哮塞,其他包可以訪問它刨秆。同樣地,如果結(jié)構(gòu)體中的字段名以大寫字母開頭忆畅,則這些字段也可以被其他包訪問衡未。
type Spec struct { //exported struct
Maker string //exported field
model string //unexported field
Price int //exported field
}
比較結(jié)構(gòu)體
結(jié)構(gòu)體是值類型,如果其字段是可比較的家凯,則該結(jié)構(gòu)體就是可以比較的缓醋。如果兩個(gè)結(jié)構(gòu)體變量的所有非空字段都相等,則認(rèn)為這兩個(gè)結(jié)構(gòu)體變量相等绊诲。
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")
}
}
在上面的程序中送粱,name 結(jié)構(gòu)體類型包含兩個(gè) string 字段。因?yàn)?string 是可比較的掂之,因此兩個(gè) name 類型的變量也是可以比較的抗俄。所以脆丁,name1 和 name2 是相等的,而 name3 和 name4 是不相等的动雹。
如果結(jié)構(gòu)體包含不可比較的類型的字段偎快,那么這兩個(gè)結(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")
}
}
在上面的程序中洽胶,image 結(jié)構(gòu)體類型包含了一個(gè)字段 data晒夹,該字段是 map 類型。map 是不可比較的類型姊氓,因此 image1 和 image2 是不可比較的丐怯。