【Go】Go语言结构体笔记

整体介绍

虽然 Go 语言不是传统意义上的面向对象语言,但它提供了结构体(struct)来组织数据,并且可以为结构体绑定方法,从而达到面向对象的部分效果。

关键知识点包括:

  • 结构体定义与实例化

    • 定义结构体时使用 type ... struct{} 语法,字段可以是各种数据类型。
    • 实例化结构体可以使用字面量、new 函数或匿名结构体语法。
  • 方法绑定

    • 为结构体绑定方法时可以选择值接收者或指针接收者。
    • 值接收者方法操作的是副本,指针接收者方法可以修改原始数据。
  • 匿名结构体

    • 无需单独定义类型,定义时直接实例化。
    • 匿名字段:结构体中直接嵌入字段(类型名作为字段名),简化代码。
  • 空结构体

    • 空结构体 struct{} 占用 0 内存,可用于实现方法接收者、作为集合的值(类似只有 key 的字典)或作为信号通道的数据类型。

接下来按照这些知识点整理代码示例。


1. 结构体的定义与实例化

1.1 定义结构体和使用字面量实例化(指针类型和非指针类型)

代码示例:

go 复制代码
// 文件名: 01_struct_definition.go
package main

import "fmt"

// 定义一个结构体 Student
type Student struct {
	id     int
	name   string
	age    int
	school string
}

func main() {
	// 使用字面量实例化结构体,并取指针(指针类型实例)
	pan := &Student{
		id:     1,
		name:   "luobozi",
		age:    18,
		school: "znlsw",
	}
	// 使用指针访问字段(语法糖支持直接 . 操作)
	fmt.Println("pan.name:", pan.name)

	// 修改字段
	pan.age = 20
	fmt.Printf("pan: %+v\n", pan)

	// 直接实例化结构体(值类型实例)
	bo := Student{
		id:   3,
		name: "luobozi",
		age:  18,
	}
	fmt.Printf("bo: %+v\n", bo)
}

说明:

  • 使用 &Student{...} 得到结构体指针;直接写 Student{...} 得到值类型实例。
  • 使用字面量可以直接初始化各个字段。

1.2 使用 new 函数实例化结构体

代码示例:

go 复制代码
// 文件名: 01_struct_new.go
package main

import "fmt"

type Student struct {
	id   int
	name string
	age  int
}

func main() {
	// 使用 new 函数实例化,返回的是指针类型
	luo := new(Student)
	luo.id = 2
	luo.name = "luobozi"
	fmt.Printf("luo: %+v\n", luo)
}

说明:

  • new(Student) 分配内存并返回指针,适用于结构体实例化;与字面量方式相比,new 返回的所有字段都是零值。

2. 值类型与指针类型的赋值

代码示例:

go 复制代码
// 文件名: 01_struct_assignment.go
package main

import "fmt"

type Student struct {
	id   int
	name string
	age  int
}

func main() {
	// 指针类型赋值:两个指针引用同一对象,修改其中一个会影响另一方
	luo := new(Student)
	luo.id = 2
	luo.name = "luobozi"

	luo2 := luo
	luo.id = 999
	fmt.Println("luo2.id:", luo2.id, "luo.id:", luo.id)

	// 值类型赋值:会拷贝一份数据,互不影响
	bo := Student{
		id:   3,
		name: "luobozi",
		age:  18,
	}
	bo2 := bo
	bo2.name = "张三"
	fmt.Println("bo2.name:", bo2.name, "bo.name:", bo.name)
}

说明:

  • 指针赋值只是复制地址,值类型赋值会拷贝整个结构体数据。

3. 方法绑定(值接收者与指针接收者)

代码示例:

go 复制代码
// 文件名: 01_struct_method.go
package main

import "fmt"

type Student struct {
	id   int
	name string
	age  int
}

// 值接收者方法:对副本操作,修改不会反映到原变量
func (s Student) ChangeName(name string) {
	fmt.Println("调用方法 ChangeName (值接收者)")
	s.name = name
}

// 指针接收者方法:修改原结构体数据
func (s *Student) ChangeName2(name string) {
	fmt.Println("调用方法 ChangeName2 (指针接收者)")
	s.name = name
}

func main() {
	bo := Student{
		id:   3,
		name: "luobozi",
		age:  18,
	}
	luo := new(Student)
	luo.id = 2
	luo.name = "luobozi"

	// 调用值接收者方法(修改不会影响原变量)
	bo.ChangeName("milamn")
	fmt.Println("bo after ChangeName:", bo)

	// 调用指针接收者方法(原变量被修改)
	luo.ChangeName("luji")
	fmt.Println("luo after ChangeName (值方式调用):", luo)

	luo.ChangeName2("mikod")
	fmt.Println("luo after ChangeName2:", luo)
}

说明:

  • 使用值接收者时,方法操作的是结构体副本;而指针接收者方法可以直接修改原数据。

4. 匿名结构体

代码示例:

go 复制代码
// 文件名: 01_struct_anonymous.go
package main

import "fmt"

func main() {
	// 定义并实例化匿名结构体,不需要提前定义类型
	abc := struct {
		abcid   int
		abcaddr string
	}{
		abcid:   10,
		abcaddr: "长沙",
	}
	fmt.Println("匿名结构体 abcaddr:", abc.abcaddr)
}

说明:

  • 匿名结构体适用于一次性使用,不需要复用结构体类型的场景。

5. 匿名字段

代码示例:

go 复制代码
// 文件名: 01_struct_anonymousField.go
package main

import "fmt"

// 定义结构体时,直接嵌入类型作为匿名字段
type Person struct {
	string
	int
}

func main() {
	// 匿名字段的赋值按照字段顺序进行
	qwe := Person{
		"niming", 2,
	}
	fmt.Printf("匿名字段 Person: %+v\n", qwe)
}

说明:

  • 匿名字段使得结构体中的字段没有显式的名字,访问时直接用类型名(或通过顺序),可以简化代码结构。

6. 空结构体及其应用

6.1 空结构体作为方法接收者

代码示例:

go 复制代码
// 文件名: 01_struct_empty.go
package main

import "fmt"

// 定义空结构体 Temp
type Temp struct{}

func (t *Temp) Call() {
	fmt.Println("call for temp")
}

func main() {
	t := &Temp{}
	t.Call()
}

说明:

  • 空结构体 struct{} 占用内存为 0,经常用作占位符或实现接口的方法接收者。

6.2 空结构体实现集合(Set)

代码示例:

go 复制代码
// 文件名: 01_struct_set.go
package main

import "fmt"

// 定义 Set 类型,其本质上是 map[string]struct{},空结构体不占用内存
type Set map[string]struct{}

// 为 Set 添加元素
func (s Set) Append(k string) {
	s[k] = struct{}{}
}

func main() {
	s := make(Set)
	s.Append("hello")
	s.Append("world")
	// 输出集合中所有的 key
	for key := range s {
		fmt.Println("set key:", key)
	}
}

说明:

  • 使用 map[string]struct{} 实现集合(只关心 key,value 为空结构体),这种方式占用内存极小,非常适合存储唯一且不可重复的键。

总结

本篇笔记涵盖了 Go 语言中结构体的核心知识点:

  1. 结构体定义与实例化 :包括指针与值的实例化方式以及使用 new 和字面量。
  2. 赋值方式:指针赋值(共享同一内存)与值赋值(拷贝数据)。
  3. 方法绑定:值接收者与指针接收者的区别。
  4. 匿名结构体:直接定义并实例化一次性使用。
  5. 匿名字段:在结构体中嵌入类型作为字段。
  6. 空结构体及集合应用:空结构体用于方法接收者、占位或实现集合。
相关推荐
专注API从业者39 分钟前
《Go 语言高并发爬虫开发:淘宝商品 API 实时采集与 ETL 数据处理管道》
开发语言·后端·爬虫·golang
Humbunklung1 小时前
PySide6 GUI 学习笔记——常用类及控件使用方法(常用类矩阵QRectF)
笔记·python·学习·pyqt
AAAA劝导tx3 小时前
List--链表
数据结构·c++·笔记·链表·list
愚润求学3 小时前
【Linux】进程优先级和进程切换
linux·运维·服务器·c++·笔记
愚润求学4 小时前
【专题四】前缀和(3)
开发语言·c++·笔记·leetcode·刷题·c++11
椰萝Yerosius4 小时前
铭记之日(3)——4.28
笔记
类似不类似5 小时前
快速配置linux远程开发-go语言
开发语言·后端·golang
ErizJ5 小时前
Golang|分布式索引架构
开发语言·分布式·后端·架构·golang
北漂老男孩6 小时前
二进制、高位低位、位移操作与进制转换全解
笔记
freexyn7 小时前
Matlab自学笔记五十二:变量名称:检查变量名称是否存在或是否与关键字冲突
人工智能·笔记·算法·matlab