10分钟上手Go语言结构体定义语法

简介: 10分钟上手Go语言结构体定义语法

/ Go 语言结构体定义详解 /

 

一、概述

结构体是 Go 语言中对数据进行抽象和封装的主要方法。本文将详细介绍 Go 语言中结构体的定义方式、创建和初始化、匿名字段等高级用法,并提供完整示例代码。

主要内容:

  • 结构体基本定义
  • 创建和初始化
  • 嵌套结构体
  • 匿名字段
  • 结构体标签
  • 可见性规则
  • 结构体方法
  • 结构体与 JSON
  • 结构体与反射

结构体是 Go 语言中复合数据类型的基石,全面掌握结构体的定义技巧,是编写易维护和扩展性强的 Go 代码的基础。


 

二、结构体基本定义

定义一个结构体需要使用 type 和 struct 关键字:

type Person struct {
  Name string
  Age  int
}

这定义了一个 Person 的结构体,有 Name 和 Age 两个字段。字段按定义顺序存储。

结构体字段上可以添加标签 tag,格式为:

FieldName tag

tag 通常用于添加元信息,可通过反射访问,常用于配置序列化。


 

三、创建和初始化

有以下几种创建结构体变量的方式:

p1 := Person{Name: "Tom", Age: 18} // 命名初始化
p2 := Person{Name: "Sam"} // 部分初始化
p3 := new(Person) // 取结构体指针
var p4 Person // 声明结构体变量

初始化时可以直接通过 Field:Value 形式初始化部分或全部字段。

new()返回对应的结构体指针,需要使用.成员访问符。还可以通过 var 声明来创建结构体变量。


 

四、嵌套结构体

结构体中可以嵌套包含另一个结构体,构成一个树形结构:

type Address struct {
  City string
  Province string
}
type User struct {
  Name string
  Gender string
  Address Address 
}

访问嵌套的结构体字段需要通过外层类型.内层类型进行访问:

user := User{
  Name: "Tom",
  Address: Address{
    City: "Beijing",
  }
}
city := user.Address.City

嵌套结构体是一个很有用的设计模式。


 

五、匿名字段

结构体可以使用匿名字段,即没有字段名的字段:

type Person struct {
  string
  int
}
p := Person{
  "Tom",
  20,
}

这里 string 和 int 就是匿名字段,在访问时直接使用类型名访问:

name := p.string // "Tom"
age := p.int // 20

匿名字段经常用于抽象定义,提高复用性。


 

六、结构体标签

前文提到结构体字段可以定义标签 tag:

type Person struct {
  Name string `json:"name"` 
  Age int `json:"age"`
}

tag 通常用于配置序列化等操作。多个 tag 可以叠加:

    Field string `json:"xxx" indo:"yyy"`

    常用的 tag 包括 json、xml、bson 等,这在和其他语言交互时非常有用。


     

    七、可见性规则

    结构体中的字段通过首字母大小写控制访问范围:

    • 大写开头的字段在包外可见(public)
    • 小写开头的字段仅包内可见(private)

    如果要在包外使用,必须通过提供 getter/setter 方法访问 private 字段:

    type Foo struct {
      publicField int
      privateField int
    }
    func (foo Foo) GetPrivate() int {
      return foo.privateField
    }
    func (foo Foo) SetPrivate(val int) {
      foo.privateField = val
    }

    这样通过方法访问 private 字段来控制可见性。


     

    八、结构体方法

    我们可以在结构体上定义方法。定义方法的格式如下:

    func (s Person) Eat() {
      // ...结构体方法
    }

    方法的接收者类型是结构体名 Person,方法名 Eat。

    调用时格式为:

    p := Person{} 
    p.Eat()

    方法作用于特定的接收者类型。不同类型,即使方法名相同,也属于不同方法。

    这就实现了基于结构体的面向对象编程。


     

    九、结构体与 JSON 序列化

    结构体经常需要序列化成 JSON 字符串传输或者保存:

    type Person struct {
      Name string `json:"name"`
      Age int `json:"age"`
    }
    p := Person{Name:"Tom", Age:20}
    data, _ := json.Marshal(p) // 序列化为JSON
    var p2 Person
    json.Unmarshal(data, &p2) // 反序列化为结构体

    这就是为什么结构体要定义 json 标签,用于指定序列化的字段名。


     

    十、结构体与反射

    反射可以让我们动态操作结构体字段和方法:

    type Foo struct {
      field1 string
      field2 int 
    }
    func main() {
      v := reflect.ValueOf(Foo{})
      // 遍历结构体字段
      for i := 0; i < v.NumField(); i++ {
        fmt.Println(v.Field(i))
      }
      // 获取字段值
      if v.FieldByName("field1").Kind() == reflect.String {
        fmt.Println("field1 is string")
      }
    }

    反射的应用可以消除代码对数据结构的依赖。


     

    十一、总结

    本文全面介绍了 Go 语言结构体的各种定义语法和技巧,包括嵌套结构体、匿名字段、结构体标签等高阶用法,并用示例代码演示了结构体的使用方式。

    结构体是 Go 语言中对数据进行抽象和封装的主要方法,熟练掌握结构体的各种技巧,可以编写出更加易维护和扩展性强的 Go 代码。


    目录
    相关文章
    |
    18天前
    |
    Go
    go语言中的数据类型
    go语言中的数据类型
    13 0
    |
    23天前
    |
    Go 开发者
    掌握Go语言:Go语言结构体,精准封装数据,高效管理实体对象(22)
    掌握Go语言:Go语言结构体,精准封装数据,高效管理实体对象(22)
    |
    5天前
    |
    数据采集 存储 Go
    使用Go语言和chromedp库下载Instagram图片:简易指南
    Go语言爬虫示例使用chromedp库下载Instagram图片,关键步骤包括设置代理IP、创建带代理的浏览器上下文及执行任务,如导航至用户页面、截图并存储图片。代码中新增`analyzeAndStoreImage`函数对图片进行分析和分类后存储。注意Instagram的反爬策略可能需要代码适时调整。
    使用Go语言和chromedp库下载Instagram图片:简易指南
    |
    23天前
    |
    存储 安全 Go
    掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
    掌握Go语言:Go语言类型转换,无缝处理数据类型、接口和自定义类型的转换细节解析(29)
    |
    1天前
    |
    安全 Go 开发者
    Golang深入浅出之-Go语言并发编程面试:Goroutine简介与创建
    【4月更文挑战第22天】Go语言的Goroutine是其并发模型的核心,是一种轻量级线程,能低成本创建和销毁,支持并发和并行执行。创建Goroutine使用`go`关键字,如`go sayHello(&quot;Alice&quot;)`。常见问题包括忘记使用`go`关键字、不正确处理通道同步和关闭、以及Goroutine泄漏。解决方法包括确保使用`go`启动函数、在发送完数据后关闭通道、设置Goroutine退出条件。理解并掌握这些能帮助开发者编写高效、安全的并发程序。
    10 1
    |
    2天前
    |
    人工智能 Go 调度
    掌握Go并发:Go语言并发编程深度解析
    掌握Go并发:Go语言并发编程深度解析
    |
    2天前
    |
    SQL 关系型数据库 MySQL
    Golang数据库编程详解 | 深入浅出Go语言原生数据库编程
    Golang数据库编程详解 | 深入浅出Go语言原生数据库编程
    |
    2天前
    |
    Go 开发者
    Golang深入浅出之-Go语言流程控制:if、switch、for循环详解
    【4月更文挑战第21天】本文介绍了Go语言中的流程控制语句,包括`if`、`switch`和`for`循环。`if`语句支持简洁的语法和初始化语句,但需注意比较运算符的使用。`switch`语句提供多分支匹配,可省略`break`,同时支持不带表达式的形式。`for`循环有多种形式,如基本循环和`for-range`遍历,遍历时修改原集合可能导致未定义行为。理解并避免易错点能提高代码质量和稳定性。通过实践代码示例,可以更好地掌握Go语言的流程控制。
    11 3
    Golang深入浅出之-Go语言流程控制:if、switch、for循环详解
    |
    2天前
    |
    Go
    Golang深入浅出之-Go语言函数基础:定义、调用与多返回值
    【4月更文挑战第21天】Go语言函数是代码组织的基本单元,用于封装可重用逻辑。本文介绍了函数定义(包括基本形式、命名、参数列表和多返回值)、调用以及匿名函数与闭包。在函数定义时,注意参数命名和注释,避免参数顺序混淆。在调用时,要检查并处理多返回值中的错误。理解闭包原理,小心处理外部变量引用,以提升代码质量和可维护性。通过实践和示例,能更好地掌握Go语言函数。
    17 1
    Golang深入浅出之-Go语言函数基础:定义、调用与多返回值
    |
    3天前
    |
    程序员 Go API
    【Go语言快速上手(二)】 分支与循环&函数讲解
    【Go语言快速上手(二)】 分支与循环&函数讲解