go语言结构体

什么是结构体?

Go语言中的结构体是一种自定义类型,它允许我们将多个不同类型的数据组合成一个聚合类型的数据结构。结构体是一个值类型,可以通过定义结构体变量来实例化。

Go语言中的结构体可以包含不同类型的字段,包括基本类型、数组、切片、映射、通道、函数、结构体等。我们可以使用点运算符访问结构体的字段。

声明和初始化

type Person struct {
    Name    string
    Age     int
    Address string
}

上面的代码定义了一个名为Person的结构体类型,它有三个字段,分别是Name、Age和Address。Name字段是一个字符串类型,Age字段是一个整数类型,Address字段是一个字符串类型。

我们可以使用结构体类型来定义一个Person结构体变量:

p := Person{
    Name:    "John",
    Age:     30,
    Address: "New York",
}

在上面的代码中,我们实例化了一个Person结构体变量p,并为其赋值。我们使用点运算符访问结构体的字段:

fmt.Println(p.Name)     // 输出:John
fmt.Println(p.Age)      // 输出:30
fmt.Println(p.Address)  // 输出:New York

Go语言中的结构体类型还支持嵌套结构体。我们可以在结构体中嵌套其他的结构体类型,从而构建更为复杂的数据结构。

下面是一个包含嵌套结构体的例子:

type Address struct {
    City  string
    State string
}

type Person struct {
    Name    string
    Age     int
    Address Address
}

p := Person{
    Name: "John",
    Age:  30,
    Address: Address{
        City:  "New York",
        State: "NY",
    },
}

fmt.Println(p.Address.City)  // 输出:New York

在上面的代码中,我们定义了两个结构体类型,一个是Address结构体类型,另一个是Person结构体类型。Person结构体类型包含一个嵌套的Address结构体类型,我们可以通过点运算符访问嵌套结构体中的字段。

结构体类型还支持方法,可以在结构体类型中定义方法,从而可以在结构体变量上调用方法来修改结构体的内部状态。

下面是一个包含方法的例子:

type Person struct {
    Name string
    Age  int
}

func (p *Person) SetName(name string) {
    p.Name = name
}

p := &Person{Name: "John", Age: 30}
p.SetName("Bob")
fmt.Println(p.Name)  // 输出:Bob

在上面的代码中,我们定义了一个SetNmae()方法,用于修改Person结构体的Name字段。SetNmae()方法使用指针接收器,可以修改Person结构体变量的内部状态。我们在结构体变量p上调用了SetName方法更改了name的值

其他特性

  1. 匿名字段

结构体类型中的字段可以是匿名的,这样就可以在访问结构体变量时直接访问匿名字段的成员。

type Address struct {
    City  string
    State string
}

type Person struct {
    Name string
    Age  int
    Address
}

p := Person{
    Name: "John",
    Age:  30,
    Address: Address{
        City:  "New York",
        State: "NY",
    },
}

fmt.Println(p.City)  // 输出:New York

在上面的代码中,我们定义了一个Person结构体类型,并将Address结构体类型作为Person结构体类型的匿名字段。这样,我们就可以直接访问Person结构体类型的City字段。

  1. 值接收器和指针接收器

在结构体类型中定义方法时,可以使用值接收器或指针接收器。使用值接收器时,方法只能访问结构体变量的副本,而使用指针接收器时,方法可以访问结构体变量的原始值,并可以修改其内部状态。

type Person struct {
    Name string
    Age  int
}

func (p Person) SetName(name string) {
    p.Name = name
}

func (p *Person) SetAge(age int) {
    p.Age = age
}

p1 := Person{Name: "John", Age: 30}
p1.SetName("Bob")
fmt.Println(p1.Name)  // 输出:John

p2 := &Person{Name: "John", Age: 30}
p2.SetAge(40)
fmt.Println(p2.Age)   // 输出:40

在上面的代码中,我们定义了两个方法,SetName()使用值接收器,SetAge()使用指针接收器。我们分别对p1和p2进行了实例化,并调用了SetName()和SetAge()方法。

由于SetName()使用的是值接收器,它只能访问结构体变量的副本,所以在输出p1.Name时,结果仍为John。而SetAge()使用的是指针接收器,它可以访问结构体变量的原始值,并修改了p2.Age的值。

  1. JSON标记

结构体类型中的字段可以使用JSON标记来指定它们在JSON编码和解码时的名称和行为。

type Person struct {
    Name string `json:"name"`
    Age  int    `json:"age"`
}

p := Person{Name: "John", Age: 30}
b, _ := json.Marshal(p)
fmt.Println(string(b))  // 输出:{"name":"John","age":30}

在上面的代码中,我们定义了一个Person结构体类型,其中的Name和Age字段都使用了JSON标记。我们将Person结构体变量p进行JSON编码,并输出编码后的结果。

  1. 内嵌结构体和方法覆盖

如果一个结构体类型内嵌了另一个结构体类型,那么它可以继承内嵌结构体类型的字段和方法,并可以对其进行覆盖。

type Address struct {
    City  string
    State string
}

func (a *Address) Print() {
    fmt.Println("City:", a.City)
    fmt.Println("State:", a.State)
}

type Person struct {
    Name string
    Age  int
    Address
}

func (p *Person) Print() {
    fmt.Println("Name:", p.Name)
    fmt.Println("Age:", p.Age)
    p.Address.Print()
}

p := Person{
    Name: "John",
    Age:  30,
    Address: Address{
        City:  "New York",
        State: "NY",
    },
}

p.Print()

在上面的代码中,我们定义了一个Address结构体类型和一个Person结构体类型,Person结构体类型内嵌了Address结构体类型。Address结构体类型有一个Print()方法,用于打印其成员变量的值。Person结构体类型也有一个Print()方法,用于打印其成员变量的值,并调用了内嵌的Address结构体类型的Print()方法。

我们创建了一个Person结构体变量p,并输出了它的值。由于Person结构体类型内嵌了Address结构体类型,所以我们可以在Person结构体类型的Print()方法中调用Address结构体类型的Print()方法,打印出City和State的值。

Go语言中的结构体类型具有丰富的特性,可以用于定义复杂的数据结构和对象。掌握这些特性可以帮助我们更好地使用结构体类型,写出更简洁、可维护、高效的代码。

最后修改:2023 年 08 月 27 日
如果觉得我的文章对你有用,请随意赞赏