💜 想真正擅长编程? 从一门课程开始,100% 免费

《笔记》第十五篇 结构体与JSON

第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中非常灵活:

  1. 作为函数参数 —— 可以将结构体传给函数
  2. 作为函数返回值 —— 函数可以返回结构体
  3. 存入数组 —— 可以创建结构体数组/切片
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 或官网查阅

八、课后练习

  1. 定义一个 Book 结构体,包含书名、作者、价格字段,创建实例并打印
  2. 在结构体中加入 time.Time 类型字段表示出版日期,注意导入 time 包
  3. 使用 json.Marshal() 将结构体转为JSON字符串并打印
  4. 将结构体中某个字段改为小写开头,观察JSON输出中该字段是否消失
  5. 使用 json:"xxx" 标签修改JSON字段名,观察输出变化
  6. 尝试用 _ 忽略 json.Marshal() 的error返回值