本文为译文 Structs
结构体是用户定义的类型。代表了一些类型的集合。
type Employee struct {
firstName string
lastName string
age int
}
//creating struct specifying field names
emp1 := Employee{
firstName: "Sam",
age: 25,
salary: 500,
lastName: "Anderson",
}
/**
not recommended
Although the above syntax saves a few lines of code, it doesn't make the field declarations explicit. Please refrain from using the above syntax.
*/
type Employee struct {
firstName, lastName string
age int
}
/**
not recommended
creating struct without specifying field names
Please refrain from using this syntax since it makes it difficult to figure out which value is for which field
*/
emp2 := Employee{"Thomas", "Paul", 29, 800}
//anonymous struct
emp3 := struct {
firstName string
lastName string
age int
salary int
}{
firstName: "Andreah",
lastName: "Nikola",
age: 31,
salary: 5000,
}
结构体的零值
package main
import (
"fmt"
)
type Employee struct {
firstName string
lastName string
age int
salary int
}
func main() {
var emp4 Employee //zero valued struct
fmt.Println(emp4)
fmt.Println("First Name:", emp4.firstName)
fmt.Println("Last Name:", emp4.lastName)
fmt.Println("Age:", emp4.age)
fmt.Println("Salary:", emp4.salary)
}
{ 0 0}
First Name:
Last Name:
Age: 0
Salary: 0
type Employee struct {
firstName string
lastName string
age int
salary int
}
emp5 := Employee{
firstName: "John",
lastName: "Paul",
}
fmt.Println("First Name:", emp5.firstName)
fmt.Println("Last Name:", emp5.lastName)
fmt.Println("Age:", emp5.age)
fmt.Println("Salary:", emp5.salary)
指向一个结构体
package main
import (
"fmt"
)
type Employee struct {
firstName string
lastName string
age int
salary int
}
func main() {
emp8 := &Employee{
firstName: "Sam",
lastName: "Anderson",
age: 55,
salary: 6000,
}
fmt.Println("First Name:", (*emp8).firstName)
fmt.Println("Age:", (*emp8).age)
}
go语言给我们了一个选项,可以使用emp8.firstName取代显示取值(*emp8).firstName来访问firstName字段。
匿名字段(anonymous fields)
package main
import (
"fmt"
)
type Person struct {
string
int
}
func main() {
p1 := Person{
string: "naveen",
int: 50,
}
fmt.Println(p1.string)
fmt.Println(p1.int)
}
匿名字段的name就是类型的名字。
嵌套结构体(nested struct)
package main
import (
"fmt"
)
type Address struct {
city string
state string
}
type Person struct {
name string
age int
address Address
}
func main() {
p := Person{
name: "Naveen",
age: 50,
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)
}
提升字段(promoted fields)
**在结构体中的匿名结构体字段的字段属于提升字段。**是不是比较绕,看个例子就好了。
package main
import (
"fmt"
)
type Address struct {
city string
state string
}
type Person struct {
name string
age int
Address
}
func main() {
p := Person{
name: "Naveen",
age: 50,
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
}
注意上面的代码,Pserson结构体有一个匿名字段Address,它是一个结构体。然后Address里面的字段city和state我们称之为promoted filed。因为他们可以被直接访问,就好像是Person结构体本身的字段一样。
可导出的结构体和字段
如果一个结构体类型是以大写开头的,那么它就可以被其他包访问。类似的如果一个结构体字段也是以大写开头的,它也可以被其他包访问。即认为是导出的。
我们写个demo理解一下
mkdir ~/Documents/structs
cd ~/Documents/structs/
go mod init structs
mkdir computer
Inside the computer directory, create a file spec.go with the following contents.
package computer
type Spec struct { //exported struct
Maker string //exported field
Price int //exported field
model string //unexported field
}
Create a file named main.go inside the structs directory and write the following program in main.go
package main
import (
"structs/computer"
"fmt"
)
func main() {
spec := computer.Spec {
Maker: "apple",
Price: 50000,
}
fmt.Println("Maker:", spec.Maker)
fmt.Println("Price:", spec.Price)
}
├── structs
│ ├── computer
│ │ └── spec.go
│ ├── go.mod
│ └── main.go
结构体相等比较(struct equality)
结构体是值类型。
如果他们的字段是可比较的,那么他们也是可比较的。
package main
import (
"fmt"
)
type name struct {
firstName string
lastName string
}
func main() {
name1 := name{
firstName: "Steve",
lastName: "Jobs",
}
name2 := name{
firstName: "Steve",
lastName: "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{
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")
}
}
./prog.go:20:12: invalid operation: image1 == image2 (struct containing map[int]int cannot be compared)