第15讲 结构体与JSON
本讲基于视频实际讲解内容整理
一、结构体(Struct)简介
老师在前面的课程中已经接触过结构体(第07讲、第10讲),本讲进一步深入讲解结构体的声明和JSON编组。
结构体是Go语言中的聚合数据类型,可以把多个不同类型的字段组合在一起。
二、结构体的声明
使用 type + struct 关键字声明结构体:
Go
type Student struct {
Name string
Age int
Address string
}
2.1 结构体可以包含任意类型
老师强调,结构体的字段可以是任意类型,包括:
- 基本类型(int、string、float等)
- 指针类型
time.Time类型(需导入time包)- Map类型
- 甚至其他结构体
Go
package main
import (
"fmt"
"time"
)
type Employee struct {
Name string
Age int
BirthDay time.Time // time.Time类型
Salary *float64 // 指针类型
Tags map[string]string // Map类型
}
func main() {
salary := 15000.0
emp := Employee{
Name: "张三",
Age: 30,
BirthDay: time.Now(),
Salary: &salary,
Tags: map[string]string{"dept": "研发"},
}
fmt.Println(emp)
}
注意:使用
time.Time类型时,必须导入time包。
三、结构体的使用场景
老师指出结构体在Go中非常灵活:
- 作为函数参数 —— 可以将结构体传给函数
- 作为函数返回值 —— 函数可以返回结构体
- 存入数组 —— 可以创建结构体数组/切片
Go
// 结构体作为函数参数
func printStudent(s Student) {
fmt.Printf("姓名: %s, 年龄: %d\n", s.Name, s.Age)
}
// 结构体作为函数返回值
func createStudent(name string, age int) Student {
return Student{Name: name, Age: age}
}
// 结构体存入数组
func main() {
students := []Student{
{Name: "张三", Age: 20},
{Name: "李四", Age: 21},
}
for _, s := range students {
printStudent(s)
}
}
四、Go标准库文档
老师在课程中提到了如何查阅Go标准库文档。Go提供了完善的官方文档:
- 官方文档网站:https://pkg.go.dev/std
- 本地可以通过
go doc命令查看
Shell
# 查看time包文档
go doc time
# 查看json包文档
go doc encoding/json
五、JSON编组(Marshal)
5.1 什么是JSON编组
JSON编组(Marshal)是将Go中的结构体数据转换为JSON格式的字节流,常用于Web接口返回数据、网络传输等场景。
5.2 json.Marshal() 函数
json.Marshal() 是Go标准库 encoding/json 包提供的函数,用于将结构体转换为JSON:
Go
package main
import (
"encoding/json"
"fmt"
)
type Student struct {
Name string
Age int
Address string
}
func main() {
s := Student{
Name: "张三",
Age: 20,
Address: "北京市朝阳区",
}
// json.Marshal 返回两个值:字节数组和error
data, err := json.Marshal(s)
if err != nil {
fmt.Println("JSON编组失败:", err)
return
}
fmt.Println(string(data))
// 输出: {"Name":"张三","Age":20,"Address":"北京市朝阳区"}
}
5.3 返回值说明
json.Marshal() 返回两个值:
| 返回值 | 类型 | 说明 |
|---|---|---|
| 第一个返回值 | []byte |
JSON格式的字节数组 |
| 第二个返回值 | error |
错误信息,成功时为nil |
5.4 用下划线忽略error
如果确定不会出错,可以用下划线 _ 忽略error返回值:
Go
data, _ := json.Marshal(s) // 忽略error
fmt.Println(string(data))
老师提醒:在生产代码中建议不要忽略error,应做错误处理。
六、首字母大小写与导出
这是Go语言中一个非常重要的规则:
| 字段首字母 | 可见性 | JSON输出 |
|---|---|---|
| 大写 | 公有(导出),其他包可访问 | ✅ 出现在JSON中 |
| 小写 | 私有(未导出),仅当前包可访问 | ❌ 不会出现在JSON中 |
Go
type Student struct {
Name string // 大写:会出现在JSON中 → "Name"
Age int // 大写:会出现在JSON中 → "Age"
address string // 小写:不会出现在JSON中
}
s := Student{Name: "张三", Age: 20, address: "北京"}
data, _ := json.Marshal(s)
fmt.Println(string(data))
// 输出: {"Name":"张三","Age":20}
// 注意:address不会出现在JSON中!
核心规则:Go通过首字母大小写来控制字段/变量/函数的可见性。大写=导出(公有),小写=未导出(私有)。这不仅影响JSON编组,也影响跨包访问。
6.1 JSON标签(Tag)
如果希望JSON中的字段名使用小写,可以通过结构体标签实现:
Go
type Student struct {
Name string `json:"name"`
Age int `json:"age"`
Address string `json:"address"`
}
// JSON输出: {"name":"张三","age":20,"address":"北京"}
七、本讲小结
| 知识点 | 要点 |
|---|---|
| 结构体声明 | type 结构体名 struct { 字段... } |
| 字段类型 | 可包含任意类型:基本类型、指针、time.Time、Map等 |
| time包 | 使用 time.Time 需导入 time 包 |
| 结构体用途 | 可作函数参数、返回值、存入数组 |
| json.Marshal() | 将结构体转为JSON,返回 ([]byte, error) |
| 下划线 _ | 忽略不需要的返回值(如error) |
| 首字母大写 | 导出(公有),JSON中可见 |
| 首字母小写 | 未导出(私有),JSON中不可见 |
| 标准库文档 | 使用 go doc 或官网查阅 |
八、课后练习
- 定义一个
Book结构体,包含书名、作者、价格字段,创建实例并打印 - 在结构体中加入
time.Time类型字段表示出版日期,注意导入time包 - 使用
json.Marshal()将结构体转为JSON字符串并打印 - 将结构体中某个字段改为小写开头,观察JSON输出中该字段是否消失
- 使用
json:"xxx"标签修改JSON字段名,观察输出变化 - 尝试用
_忽略json.Marshal()的error返回值