在Go语言中,struct
(结构体)是一种复合数据类型,用于将多个字段(属性)组合在一起,形成自定义的复杂数据类型。struct
非常适合用于描述对象或实体的属性和行为。
1. 定义和声明struct
Go语言中,使用type
关键字定义结构体,并使用struct
关键字定义字段。
示例 1:定义和声明结构体
package mainimport "fmt"// 定义一个结构体类型
type Person struct {Name stringAge intCity string
}func main() {// 声明结构体变量并初始化var p1 Personp1.Name = "Alice"p1.Age = 25p1.City = "New York"fmt.Println("Person:", p1)
}
2. 使用字面量初始化结构体
可以使用字面量语法直接初始化结构体的字段值。
package mainimport "fmt"type Person struct {Name stringAge intCity string
}func main() {// 使用字面量初始化p1 := Person{Name: "Bob", Age: 30, City: "Los Angeles"}fmt.Println("Person:", p1)// 忽略部分字段p2 := Person{Name: "Charlie"}fmt.Println("Partial Initialization:", p2) // Age 和 City 将被设为默认值0和""
}
3. 匿名字段
Go支持匿名字段,即可以在结构体中直接嵌入一个数据类型作为字段,字段名默认为该数据类型的名称。
package mainimport "fmt"type Person struct {string // 匿名字段,类型为字段名int // 匿名字段,类型为字段名
}func main() {p := Person{"Alice", 25}fmt.Println("Person:", p)fmt.Println("Name:", p.string)fmt.Println("Age:", p.int)
}
4. 嵌套结构体
结构体支持嵌套,可以作为其他结构体的字段。
package mainimport "fmt"// 地址结构体
type Address struct {City stringZipCode int
}// 人物结构体
type Person struct {Name stringAge intAddress // 嵌套的结构体
}func main() {p := Person{Name: "David",Age: 40,Address: Address{City: "Miami", ZipCode: 33101},}fmt.Println("Person:", p)fmt.Println("City:", p.City) // 可直接访问嵌套字段fmt.Println("Zip Code:", p.ZipCode)
}
5. 结构体方法
结构体可以定义方法(与字段相关的函数)。方法的接收者可以是结构体类型的值或指针。
示例:定义结构体方法
package mainimport "fmt"type Rectangle struct {Width, Height float64
}// 方法:计算矩形面积
func (r Rectangle) Area() float64 {return r.Width * r.Height
}// 方法:修改矩形的宽度
func (r *Rectangle) SetWidth(width float64) {r.Width = width
}func main() {rect := Rectangle{Width: 10, Height: 5}fmt.Println("Area:", rect.Area())// 使用方法修改宽度rect.SetWidth(20)fmt.Println("Updated Rectangle:", rect)fmt.Println("Updated Area:", rect.Area())
}
*Rectangle
是指针接收者(pointer receiver)
- 指针接收者 vs 值接收者
在 Go 语言中,方法可以定义在值类型或指针类型上。这意味着你可以选择使用值接收者或指针接收者来定义方法。
值接收者
func (r Rectangle) SetWidth(width float64) {r.Width = width
}
- 值接收者:方法接收的是调用者的副本。对副本的修改不会影响原始对象。
- 适用场景:当方法不需要修改接收者本身时,可以使用值接收者。
指针接收者
func (r *Rectangle) SetWidth(width float64) {r.Width = width
}
- 指针接收者:允许方法修改接收者对象的状态。
- 值接收者:方法接收到的是接收者对象的副本,修改不会影响原始对象。
6. 使用结构体指针
结构体的指针可以直接访问字段,无需解引用。通过结构体指针修改字段值时会直接影响原结构体。
package mainimport "fmt"type Person struct {Name stringAge int
}func main() {p := &Person{Name: "Eve", Age: 35} // 指针形式声明fmt.Println("Original Person:", *p)p.Age = 36 // 直接通过指针修改字段值fmt.Println("Updated Person:", *p)
}
7. 结构体比较
Go语言中,只有可比较的字段才能比较两个结构体是否相等。所有字段可比较时,结构体才可直接比较。
package mainimport "fmt"type Point struct {X, Y int
}func main() {p1 := Point{X: 1, Y: 2}p2 := Point{X: 1, Y: 2}p3 := Point{X: 2, Y: 3}fmt.Println("p1 == p2:", p1 == p2) // 相等fmt.Println("p1 == p3:", p1 == p3) // 不相等
}
8. 匿名结构体
Go支持匿名结构体,适合用于快速创建临时结构体。
package mainimport "fmt"func main() {// 匿名结构体p := struct {Name stringAge int}{Name: "Frank",Age: 28,}fmt.Println("Anonymous Struct:", p)
}
9. 将结构体作为函数参数
结构体作为函数参数时,可以是值传递或指针传递。
- 值传递:创建结构体副本,不会影响原结构体。
- 指针传递:传递结构体指针,可以修改原结构体。
示例
package mainimport "fmt"type Person struct {Name stringAge int
}// 值传递
func increaseAge(p Person) {p.Age += 1
}// 指针传递
func increaseAgePtr(p *Person) {p.Age += 1
}func main() {p := Person{Name: "Grace", Age: 22}increaseAge(p)fmt.Println("After value passing:", p) // 年龄不变increaseAgePtr(&p)fmt.Println("After pointer passing:", p) // 年龄增加
}
- 定义结构体:使用
type
和struct
关键字。 - 初始化:可以通过字面量、
new
或指针形式初始化。 - 方法:使用方法定义结构体行为,接收者可以是值或指针。
- 嵌套结构体:可以嵌套其他结构体,实现继承效果。
- 比较:仅当结构体所有字段可比较时,才能直接比较两个结构体是否相等。