Go结构体(struct)

在Go语言中,struct(结构体)是一种复合数据类型,用于将多个字段(属性)组合在一起,形成自定义的复杂数据类型。struct非常适合用于描述对象或实体的属性和行为。

1. 定义和声明struct

Go语言中,使用type关键字定义结构体,并使用struct关键字定义字段。

示例 1:定义和声明结构体
go 复制代码
package main

import "fmt"

// 定义一个结构体类型
type Person struct {
    Name string
    Age  int
    City string
}

func main() {
    // 声明结构体变量并初始化
    var p1 Person
    p1.Name = "Alice"
    p1.Age = 25
    p1.City = "New York"

    fmt.Println("Person:", p1)
}

2. 使用字面量初始化结构体

可以使用字面量语法直接初始化结构体的字段值。

go 复制代码
package main

import "fmt"

type Person struct {
    Name string
    Age  int
    City 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支持匿名字段,即可以在结构体中直接嵌入一个数据类型作为字段,字段名默认为该数据类型的名称。

go 复制代码
package main

import "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. 嵌套结构体

结构体支持嵌套,可以作为其他结构体的字段。

go 复制代码
package main

import "fmt"

// 地址结构体
type Address struct {
    City    string
    ZipCode int
}

// 人物结构体
type Person struct {
    Name    string
    Age     int
    Address // 嵌套的结构体
}

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. 结构体方法

结构体可以定义方法(与字段相关的函数)。方法的接收者可以是结构体类型的值或指针。

示例:定义结构体方法
go 复制代码
package main

import "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)

  1. 指针接收者 vs 值接收者

在 Go 语言中,方法可以定义在值类型或指针类型上。这意味着你可以选择使用值接收者或指针接收者来定义方法。

值接收者

go 复制代码
func (r Rectangle) SetWidth(width float64) {
    r.Width = width
}
  • 值接收者:方法接收的是调用者的副本。对副本的修改不会影响原始对象。
  • 适用场景:当方法不需要修改接收者本身时,可以使用值接收者。

指针接收者

go 复制代码
func (r *Rectangle) SetWidth(width float64) {
    r.Width = width
}
  • 指针接收者:允许方法修改接收者对象的状态。
  • 值接收者:方法接收到的是接收者对象的副本,修改不会影响原始对象。

6. 使用结构体指针

结构体的指针可以直接访问字段,无需解引用。通过结构体指针修改字段值时会直接影响原结构体。

go 复制代码
package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

func main() {
    p := &Person{Name: "Eve", Age: 35} // 指针形式声明
    fmt.Println("Original Person:", *p)

    p.Age = 36 // 直接通过指针修改字段值
    fmt.Println("Updated Person:", *p)
}

7. 结构体比较

Go语言中,只有可比较的字段才能比较两个结构体是否相等。所有字段可比较时,结构体才可直接比较。

go 复制代码
package main

import "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支持匿名结构体,适合用于快速创建临时结构体。

go 复制代码
package main

import "fmt"

func main() {
    // 匿名结构体
    p := struct {
        Name string
        Age  int
    }{
        Name: "Frank",
        Age:  28,
    }

    fmt.Println("Anonymous Struct:", p)
}

9. 将结构体作为函数参数

结构体作为函数参数时,可以是值传递或指针传递。

  • 值传递:创建结构体副本,不会影响原结构体。
  • 指针传递:传递结构体指针,可以修改原结构体。
示例
go 复制代码
package main

import "fmt"

type Person struct {
    Name string
    Age  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) // 年龄增加
}
  • 定义结构体 :使用typestruct关键字。
  • 初始化 :可以通过字面量、new或指针形式初始化。
  • 方法:使用方法定义结构体行为,接收者可以是值或指针。
  • 嵌套结构体:可以嵌套其他结构体,实现继承效果。
  • 比较:仅当结构体所有字段可比较时,才能直接比较两个结构体是否相等。
相关推荐
安冬的码畜日常11 分钟前
【Vim Masterclass 笔记24】S10L43 + L44:同步练习10 —— 基于 Vim 缓冲区的各类基础操作练习(含点评课)
笔记·vim·自学笔记·vim同步练习·vim缓冲区·vim buffer·vim缓冲区练习
一只码代码的章鱼20 分钟前
粒子群算法 笔记 数学建模
笔记·算法·数学建模·逻辑回归
圆圆滚滚小企鹅。26 分钟前
刷题笔记 贪心算法-1 贪心算法理论基础
笔记·算法·leetcode·贪心算法
杨过姑父42 分钟前
ES6 简单练习笔记--变量申明
前端·笔记·es6
l1x1n01 小时前
No.37 笔记 | Python面向对象编程学习笔记:探索代码世界的奇妙之旅
笔记·python·学习
路上阡陌1 小时前
Java学习笔记(二十四)
java·笔记·学习
束照2 小时前
noteboolm 使用笔记
笔记·notebooklm
安冬的码畜日常2 小时前
【Vim Masterclass 笔记23】第十章:Vim 缓冲区与多窗口的用法概述 + S10L42:Vim 缓冲区的用法详解与多文件编辑
笔记·vim·buffer·vim缓冲区·vim buffer·vim多文件编辑·vim多文件
初九之潜龙勿用3 小时前
我的创作纪念日,纪念我的第512天
笔记
雾里看山5 小时前
【MySQL】 库的操作
android·数据库·笔记·mysql