在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
什么是结构体?结构体是用户定义的类型,表示若干个字段(Field)的集合。有时应该把数据整合在一起,而不是让这些数据没有联系。这种情况下可以使用结构体。 例如,一个职员有 结构体的声明type Employee struct { firstName string lastName string age int } 在上面的代码片段里,声明了一个结构体类型 type Employee struct { firstName, lastName string age, salary int } 上面的结构体 声明结构体时也可以不用声明一个新类型,这样的结构体类型称为 匿名结构体(Anonymous Structure)。 var employee struct { firstName, lastName string age int } 上述代码片段创建一个匿名结构体 创建命名的结构体通过下面代码,我们定义了一个命名的结构体 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) } 在线运行程序 在上述程序的第 7 行,我们创建了一个命名的结构体 在上面程序的第 23 行,定义 该程序将输出: 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) } 在线运行程序 在上述程序的第 3 行,我们定义了一个匿名结构体变量 该程序会输出: 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) } 在线运行程序 该程序定义了 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) } 在线运行程序 在上面程序中的第 14 行和第 15 行,我们初始化了 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) } 在线运行程序 上面程序中的 emp6.firstName 访问了结构体 First Name: Sam Last Name: Anderson Age: 55 Salary: $6000 还可以创建零值的 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) } 在线运行程序 在上面程序中,我们定义了 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) } 在线运行程序 在上面程序中,emp8 是一个指向结构体 First Name: Sam Age: 55 Go 语言允许我们在访问 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) } 在线运行程序 在上面的程序中,我们使用 First Name: Sam Age: 55 匿名字段当我们创建结构体时,字段可以只有类型,而没有字段名。这样的字段称为匿名字段(Anonymous Field)。 以下代码创建一个 type Person struct { string int } 我们接下来使用匿名字段来编写一个程序。 package main import ( "fmt" ) type Person struct { string int } func main() { p := Person{"Naveen", 50} fmt.Println(p) } 在线运行程序 在上面的程序中,结构体 虽然匿名字段没有名称,但其实匿名字段的名称就默认为它的类型。比如在上面的 package main import ( "fmt" ) type Person struct { string int } func main() { var p1 Person p1.string = "naveen" p1.int = 50 fmt.Println(p1) } 在线运行程序 在上面程序的第 14 行和第 15 行,我们访问了 {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) } 在线运行程序 上面的结构体 Name: Naveen Age: 50 City: Chicago State: Illinois 提升字段(Promoted Fields)如果是结构体中有匿名的结构体类型字段,则该匿名结构体里的字段就称为提升字段。这是因为提升字段就像是属于外部结构体一样,可以用外部结构体直接访问。我知道这种定义很复杂,所以我们直接研究下代码来理解吧。 type Address struct { city, state string } type Person struct { name string age int Address } 在上面的代码片段中, 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 } 在线运行程序 在上面代码中的第 26 行和第 27 行,我们使用了语法 Name: Naveen Age: 50 City: Chicago State: Illinois 导出结构体和字段如果结构体名称以大写字母开头,则它是其他包可以访问的导出类型(Exported Type)。同样,如果结构体里的字段首字母大写,它也能被其他包访问到。 让我们使用自定义包,编写一个程序来更好地去理解它。 在你的 Go 工作区的 在 package computer type Spec struct { //exported struct Maker string //exported field model string //unexported field Price int //exported field } 上面的代码片段中,创建了一个 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 行,我们导入了 如果我们试图访问未导出的字段 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 行,我们试图访问未导出的字段 结构体相等性(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") } } 在线运行程序 在上面的代码中,结构体类型 上面代码中 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") } } 在线运行程序 在上面代码中,结构体类型
作者:Nick Coghlan 本文由 GCTT 原创编译,Go 中文网 荣誉推出 |
请发表评论