Golang struct 关键字
最后修改于 2025 年 5 月 7 日
本教程将介绍如何在 Go 中使用 struct 关键字。我们将通过创建和使用自定义类型的实际示例来涵盖 struct 的基础知识。
struct 关键字定义了一个复合数据类型,它将多个变量组合在一个名称下。Structs 是在 Go 中创建复杂数据结构的基础。
在 Go 中,structs 可以包含不同类型的字段、方法,并且可以实现接口。它们提供了一种创建自定义类型的方式,用于模拟现实世界中的实体和关系。
基本 struct 定义
最简单的 struct 包含带有其类型的命名字段。本示例展示了如何定义和初始化一个基本的 struct。
package main
import "fmt"
type Person struct {
Name string
Age int
}
func main() {
var p1 Person
p1.Name = "Alice"
p1.Age = 30
p2 := Person{"Bob", 25}
fmt.Println(p1)
fmt.Println(p2)
}
我们定义了一个带有 Name 和 Age 字段的 Person struct。示例展示了两种初始化方法:逐个字段初始化和使用 struct 字面量。
匿名 structs
Go 支持匿名 structs,用于一次性使用场景。本示例演示了创建和使用未命名 struct 类型。
package main
import "fmt"
func main() {
book := struct {
Title string
Author string
Pages int
}{
Title: "The Go Programming Language",
Author: "Alan Donovan",
Pages: 380,
}
fmt.Printf("%+v\n", book)
}
匿名 struct 在一步中定义和初始化。当您需要一个临时结构而无需声明新类型时,这很有用。
嵌套 structs
Structs 可以包含其他 structs 来模拟复杂的关系。本示例展示了嵌套 struct 的组合。
package main
import "fmt"
type Address struct {
Street string
City string
Country string
}
type Person struct {
Name string
Age int
Address Address
}
func main() {
p := Person{
Name: "Charlie",
Age: 35,
Address: Address{
Street: "123 Main St",
City: "Boston",
Country: "USA",
},
}
fmt.Printf("%+v\n", p)
}
Person struct 包含一个 Address struct。这创建了一个模拟现实世界关系的层次数据结构。
Struct 方法
Structs 可以附加方法。本示例演示了在 struct 类型上定义和调用方法。
package main
import "fmt"
type Rectangle struct {
Width float64
Height float64
}
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
func (r *Rectangle) Scale(factor float64) {
r.Width *= factor
r.Height *= factor
}
func main() {
rect := Rectangle{Width: 10, Height: 5}
fmt.Println("Area:", rect.Area())
rect.Scale(2)
fmt.Println("Scaled Area:", rect.Area())
}
Area 方法使用值接收器,而 Scale 使用指针接收器。指针接收器可以修改原始 struct。
Struct 标签
Struct 标签提供关于字段的元数据。本示例展示了用于序列化的 JSON 标签。
package main
import (
"encoding/json"
"fmt"
)
type User struct {
ID int `json:"id"`
Username string `json:"username"`
Email string `json:"email,omitempty"`
IsActive bool `json:"-"`
}
func main() {
u := User{
ID: 1,
Username: "johndoe",
Email: "",
IsActive: true,
}
data, _ := json.Marshal(u)
fmt.Println(string(data))
}
标签控制 JSON 字段名称和行为。omitempty 用于跳过空字段,而 - 用于从序列化中排除字段。
Struct 嵌入
Go 支持通过嵌入 structs 来实现组合。本示例演示了字段和方法的提升。
package main
import "fmt"
type Contact struct {
Email string
Phone string
}
func (c Contact) Info() string {
return fmt.Sprintf("%s | %s", c.Email, c.Phone)
}
type Employee struct {
Name string
Contact
}
func main() {
emp := Employee{
Name: "Jane Doe",
Contact: Contact{
Email: "jane@example.com",
Phone: "555-1234",
},
}
fmt.Println(emp.Info())
fmt.Println(emp.Email)
}
Contact 的字段和方法被提升到 Employee struct。这提供了一种在没有继承的情况下组合功能的方式。
Struct 比较
如果所有字段都可比较,则 structs 可以进行比较。本示例展示了 struct 实例之间的相等性检查。
package main
import "fmt"
type Point struct {
X, Y int
}
func main() {
p1 := Point{1, 2}
p2 := Point{1, 2}
p3 := Point{2, 3}
fmt.Println("p1 == p2:", p1 == p2)
fmt.Println("p1 == p3:", p1 == p3)
type Person struct {
Name string
Age int
}
// person1 := Person{"Alice", 30}
// person2 := Person{"Alice", 30}
// fmt.Println(person1 == person2) // Valid
// type Data struct {
// Info map[string]string
// }
// d1 := Data{Info: make(map[string]string)}
// d2 := Data{Info: make(map[string]string)}
// fmt.Println(d1 == d2) // Invalid: map fields are not comparable
}
具有可比较字段的 structs 可以使用 == 进行比较。该示例还显示了由于不可比较字段而无法进行比较的情况。
来源
本教程通过创建和使用自定义数据结构的实际示例,涵盖了 Go 中的 struct 关键字。