当前位置: 首页 > article >正文

【Go】Go语言结构体笔记

整体介绍

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

  • 结构体定义与实例化

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

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

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

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

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


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

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

代码示例:

// 文件名: 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 函数实例化结构体

代码示例:

// 文件名: 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. 值类型与指针类型的赋值

代码示例:

// 文件名: 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. 方法绑定(值接收者与指针接收者)

代码示例:

// 文件名: 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. 匿名结构体

代码示例:

// 文件名: 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. 匿名字段

代码示例:

// 文件名: 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 空结构体作为方法接收者

代码示例:

// 文件名: 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)

代码示例:

// 文件名: 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. 空结构体及集合应用:空结构体用于方法接收者、占位或实现集合。

http://www.kler.cn/a/598079.html

相关文章:

  • 自定义mavlink 生成wireshark wlua插件错误(已解决)
  • HTTP长连接与短连接的前世今生
  • 2025年01月02日浙江鼎永前端面试
  • 大模型RLHF训练-PPO算法详解:Proximal Policy Optimization Algorithms
  • Linux shell脚本2-test条件测试语句:文件类型、字符串是否相等、数字大小比较、多重条件判断,测试语句验证
  • Xss Game1-8关通关
  • IM 基于 WebRtc 视频通信功能
  • Mongodb分片模式部署
  • CATIA二次开发:基于牛顿迭代法的参数化衰减球体生成系统
  • 【Flask公网部署】采用Nginx+gunicorn解决Flask框架静态资源无法加载的问题
  • ECMAScript、DOM和BOM是个啥(通俗地来讲)
  • Netty——NIO 空轮询 bug
  • Redis + 布隆过滤器解决缓存穿透问题
  • Kafka-1
  • Redis、Memcached应用场景对比
  • 字节DAPO算法:改进DeepSeek的GRPO算法-解锁大规模LLM强化学习的新篇章(代码实现)
  • 数据结构 -- 线索二叉树
  • 针对永磁电机(PMM)的d轴和q轴电流,考虑交叉耦合补偿,设计P1控制器并推导出相应的传递函数
  • 2025.3.17-2025.3.23学习周报
  • 银河麒麟桌面版包管理器(一)