8.1 Go Struct 结构体基础知识学习笔记

8.1 Go Struct 结构体基础知识学习笔记

1. 定义结构体

结构体是自定义类型,用于将相关数据组合在一起。

type Person struct {
    Name string
    Age  int
}

type Book struct {
    Title  string
    Author string
    Pages  int
}

type Address struct {
    Street string
    City   string
    State  string
    Zip    string
}

要点

  • 字段名大写开头 → 其他包可访问(public)
  • 字段名小写开头 → 仅当前包可访问(private)
  • 每个字段占一行,类型跟在字段名后面

2. 创建结构体实例的三种方式

方式一:指定字段名(推荐)

person1 := Person{Name: "Alice", Age: 30}

优点:字段顺序无关,可读性好,不容易出错。

方式二:不指定字段名(位置参数)

person2 := Person{"Bob", 25}

必须按定义时的字段顺序填写所有字段,少写或顺序错都会编译报错。实际开发中不推荐使用。

方式三:零值 + 逐个赋值

var person3 Person        // 所有字段为零值:Name="", Age=0
person3.Name = "Charlie"  // 逐个赋值
person3.Age = 35

var 声明的结构体,所有字段自动初始化为类型的零值(string 为 "",int 为 0,bool 为 false)。


3. 访问和修改字段

使用 . 操作符:

fmt.Printf("Person1: Name=%s, Age=%d\n", person1.Name, person1.Age)

book.Pages += 20  // 修改字段值

4. 结构体嵌入(嵌套)

结构体可以嵌入另一个结构体作为字段,有两种写法:

写法一:具名嵌入

type Student struct {
    Name    string
    ID      int
    Address Address  // 具名字段,必须通过 student.Address.City 访问
}

访问时需要写完整路径:

fmt.Printf("City: %s\n", student.Address.City)

写法二:匿名嵌入(嵌入式)

type Student struct {
    Name string
    ID   int
    Address  // 匿名嵌入,字段提升,可直接访问 student.City
}

访问时可以直接用字段名(字段提升):

fmt.Printf("City: %s\n", student.City)        // 直接访问
fmt.Printf("Address: %+v\n", student.Address)  // 也可以整体访问

初始化方式相同:

student := Student{
    Name: "Diana",
    ID:   12345,
    Address: Address{
        Street: "123 Main St",
        City:   "Boston",
        State:  "MA",
        Zip:    "02101",
    },
}

5. 结构体比较

如果所有字段类型都可比较(string、int、bool 等),结构体可以直接用 == 比较:

person1 := Person{Name: "Alice", Age: 30}
person4 := Person{Name: "Alice", Age: 30}

if person1 == person4 {
    fmt.Println("person1 and person4 are equal")  // 输出: equal
}

注意:如果结构体包含不可比较的字段(如 slice、map),则不能用 == 比较,编译会报错。


6. 结构体是值类型(拷贝而非引用)

赋值结构体会创建一个独立的副本,修改副本不影响原值:

personCopy := person1       // 创建副本
personCopy.Age = 31         // 修改副本

fmt.Printf("Original: %+v\n", person1)   // {Name:Alice Age:30}
fmt.Printf("Copy: %+v\n", personCopy)     // {Name:Alice Age:31}

person1 的 Age 仍然是 30,personCopy 的 Age 是 31,两者互不影响。

如果想要引用(修改副本也修改原值),需要使用指针

personPtr := &person1       // 指针,指向同一个实例
personPtr.Age = 31          // 修改指针指向的值

fmt.Printf("Original: %+v\n", person1)   // {Name:Alice Age:31} — 原值也被修改了

7. 格式化输出

格式化动词 输出 示例
%v 默认格式 {Alice 30}
%+v 带字段名 {Name:Alice Age:30}
%#v Go 语法表示 main.Person{Name:"Alice", Age:30}

知识点总结

知识点 关键概念
定义结构体 type Name struct { ... },字段大写=公开,小写=私有
创建实例 三种方式:指定字段名、位置参数、零值逐个赋值
访问/修改字段 . 操作符,如 person.Name
嵌入结构体 具名嵌入 vs 匿名嵌入(匿名嵌入有字段提升)
比较 字段类型都可比较时,可用 ==
值类型 赋值产生独立副本,想共享需用指针
格式化输出 %+v 带字段名,最常用
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

友情链接更多精彩内容