Go 结构体

Go 语言中结构体(struct)自定义复合类型,用来将多个不同类型的字段(变量)组合在一起,描述一个事物的属性,相当于其他语言的「类」,但 Go 没有类,结构体是实现面向对象编程的核心。

一、基础定义与声明

1. 定义结构体

使用 type + struct 关键字定义:

复制代码
// 语法
type 结构体名 struct {
    字段名 字段类型
    字段名 字段类型
    // ...
}

示例:定义一个「人」的结构体

复制代码
// 定义 Person 结构体
type Person struct {
    Name string // 姓名
    Age  int    // 年龄
    City string // 城市
}

2. 创建结构体实例(赋值)

有 4 种常用方式:

复制代码
package main

import "fmt"

type Person struct {
	Name string
	Age  int
	City string
}

func main() {
	// 方式1:按字段顺序赋值(必须严格对应)
	p1 := Person{"张三", 20, "北京"}

	// 方式2:指定字段名赋值(推荐,顺序无关)
	p2 := Person{Name: "李四", Age: 25}

	// 方式3:先声明,后赋值
	var p3 Person
	p3.Name = "王五"
	p3.Age = 30
	p3.City = "上海"

	// 方式4:指针方式创建(推荐用于大结构体,节省内存)
	p4 := Person{Name: "赵六", Age: 35, City: "深圳"}

	// 打印结果
	fmt.Println(p1, p2, p3, p4)
}

3. 访问结构体字段

直接使用 . 访问:

复制代码
// 普通实例
fmt.Println(p1.Name) // 输出:张三
p1.Age = 21          // 修改字段

// 指针实例(Go 自动解引用,无需写 *)
fmt.Println(p4.City) // 输出:深圳

二、结构体进阶用法

1. 结构体嵌套(组合)

结构体可以嵌套其他结构体,实现「属性包含」:

复制代码
// 地址结构体
type Address struct {
	Province string
	Street   string
}

// 用户结构体(嵌套 Address)
type User struct {
	ID      int
	Username string
	Addr    Address // 嵌套结构体
}

// 使用
u := User{
	ID:       1,
	Username: "admin",
	Addr: Address{
		Province: "广东",
		Street:   "科技园路",
	},
}

// 访问嵌套字段
fmt.Println(u.Addr.Province) // 输出:广东

2. 匿名嵌套(简化访问)

省略字段名,直接嵌套结构体类型,可以直接访问嵌套字段

复制代码
type User struct {
	ID      int
	Username string
	Address  // 匿名嵌套
}

// 使用
u := User{
	ID:       1,
	Username: "admin",
	Address: Address{Province: "广东", Street: "科技园路"},
}

// 直接访问匿名嵌套字段(简化写法)
fmt.Println(u.Province) // 直接访问,无需 u.Address.Province

3. 结构体方法(给结构体绑定函数)

这是 Go 实现「面向对象」的核心,给结构体定义专属函数(方法):

复制代码
// 语法:func (接收者 结构体类型) 方法名() 返回值 {}

// 给 Person 定义一个打招呼的方法
func (p Person) SayHello() {
	fmt.Printf("大家好,我是 %s,今年 %d 岁\n", p.Name, p.Age)
}

// 定义修改年龄的方法(必须用指针接收者,否则修改的是副本)
func (p *Person) GrowUp() {
	p.Age++
}

// 使用
p := Person{Name: "张三", Age: 20}
p.SayHello()   // 输出:大家好,我是 张三,今年 20 岁
p.GrowUp()     // 年龄+1
fmt.Println(p.Age) // 输出:21
接收者两种类型区别

表格

接收者类型 用法 适用场景
值接收者 (p Person) 不修改原结构体,只读操作 获取数据、打印、计算
指针接收者 (p *Person) 可修改原结构体,节省内存 修改字段、大结构体避免拷贝

4. 结构体标签(Tag)

结构体字段后加反引号 key:"value",用于序列化、数据库映射、校验等(最常用在 JSON 转换):

复制代码
type User struct {
	ID       int    `json:"user_id" db:"id"`    // JSON 字段名改为 user_id
	Username string `json:"username" db:"name"` // 数据库映射为 name
	Age      int    `json:"age,omitempty"`      // 为空时忽略该字段
}

三、零值与初始化

  • 结构体未赋值时,所有字段为对应类型零值(字符串空、数字 0、指针 nil)
  • 可以使用 new() 初始化,返回指针:

四、结构体比较

  • 相同结构体类型 可以直接用 == 比较(所有字段都相等则结构体相等)
  • 包含切片、map 等不可比较类型的结构体,不能用 == 比较

五、完整实战示例

复制代码
package main

import "encoding/json"
import "fmt"

// 定义结构体 + 标签
type Student struct {
	ID    int    `json:"id"`
	Name  string `json:"name"`
	Score float64`json:"score"`
}

// 结构体方法:获取成绩等级
func (s Student) GetLevel() string {
	if s.Score >= 90 {
		return "A"
	} else if s.Score >= 60 {
		return "B"
	}
	return "C"
}

func main() {
	// 1. 创建实例
	stu := Student{ID: 1, Name: "小明", Score: 95.5}

	// 2. 调用方法
	fmt.Println("成绩等级:", stu.GetLevel()) // A

	// 3. 结构体转 JSON
	jsonData, _ := json.Marshal(stu)
	fmt.Println("JSON:", string(jsonData))
	// 输出:{"id":1,"name":"小明","score":95.5}
}

总结

  1. 结构体是 Go 的复合类型,用于封装多个不同类型字段,描述事物属性
  2. 核心用法:定义结构体 → 创建实例 → 访问字段 → 绑定方法
  3. 指针接收者用于修改结构体 ,值接收者用于只读操作
  4. 标签(Tag)常用于 JSON、数据库等场景的字段映射
  5. 结构体是 Go 面向对象编程的基础,替代了其他语言的「类」
相关推荐
xuhaoyu_cpp_java4 小时前
连接池学习
数据库·经验分享·笔记·学习
东京老树根6 小时前
SAP学习笔记 - BTP SAP Build05 - SAP BTP BPA简介,Email Destination Settings(TODO)
笔记·学习
talen_hx2966 小时前
《零基础入门Spark》学习笔记 Day 17
大数据·笔记·学习·spark
北山有鸟6 小时前
Linux第一宏:container_of
笔记·嵌入式硬件·学习
做cv的小昊7 小时前
【TJU】研究生应用统计学课程笔记(2)——第一章 数理统计的基本知识(1.3 统计中常用的分布族)
笔记·线性代数·数学建模·矩阵·概率论·学习方法·抽象代数
ouliten7 小时前
cuda编程笔记(38)--CUDA 异步回调
笔记·cuda
Better Bench7 小时前
《八十天环游地球》阅读笔记
笔记·读书笔记·八十天环游地球
sheeta19987 小时前
LeetCode 每日一题笔记 日期:2026.04.21 题目:1722. 执行交换操作后的最小汉明距离
笔记·算法·leetcode
贺小涛8 小时前
python和golang进程、线程、协程区别
java·python·golang