Go中(_)字段有什么特殊用途?

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
云原生内存数据库 Tair,内存型 2GB
云数据库 Redis 版,标准版 2GB
推荐场景:
搭建游戏排行榜
简介: 在Go语言中,结构体`User`含`Name`和`Age`字段。不带下划线的结构体可以用位置或具名初始化。但若添加下划线字段`_`,仅能通过零值或具名初始化,因`_`是未导出字段,位置初始化会导致编译错误。这样设计可提高代码可读性和避免顺序错误。

首先,我们来看不包含下划线(_)字段的结构体代码示例。

model 包里定义一个 User 结构体,包含 NameAge 两个字段。

go

代码解读

复制代码

type User struct {
    Name string
    Age  int
}

使用 位置初始化具名字段初始化 两种方式声明结构体变量。

go

代码解读

复制代码

user := model.User{"陈明勇", 18}
user = model.User{Name: "陈明勇", Age: 18}

在上述代码中,无论是定义结构体,还是声明结构体,都没有任何问题。

我们再来看下包含下划线(_)字段的结构体代码例子:

model 包里定义一个 User 结构体,包含 NameAge 以及 _ 三个字段。

go

代码解读

复制代码

type User struct {
    Name string
    Age  int
    _    struct{}
}

使用 位置初始化具名字段初始化 两种方式声明结构体变量。

go

代码解读

复制代码

// 编译错误 too few values in struct literal of type model.User
user := model.User{"陈明勇", 18}
// 编译错误 implicit assignment to unexported field _ in struct literal of type model.User
user = model.User{"陈明勇", 18, struct{}{}}
// 正常
user = model.User{}
user = model.User{Name: "陈明勇", Age: 18}

在上述例子中,如果通过 user := model.User{"陈明勇", 18}model.User{"陈明勇", 18, struct{}{}} 这两种 位置初始化 的方式声明结构体变量,程序将会编译错误,而通过 零值初始化具名字段初始化 的方式去声明结构体变量则没有问题。

通过对比有无下划线(_)字段的结构体代码示例,我们可以总结出在结构体中定义下划线(_)字段的用途:在结构体中定义一个名为 _ 的字段,可以强制要求该结构体在初始化时必须使用具名字段初始化(声明零值结构体变量的场景除外)。

原理浅析

当我们使用 位置初始化 的方式声明结构体时,需要按照结构体字段的顺序依次提供所有字段的值。

如果在结构体中定义了一个名为 _ 的字段,那么使用 位置初始化 的方式时,如果没有提供 _ 字段的值,编译器会提示 too few values in struct literal of type XXX,这是因为没有提供所有的结构体字段值。

即使按照结构体字段的顺序提供了所有字段的值,编译器也会报错,提示 implicit assignment to unexported field _ in struct literal of type XXX。这是因为 _ 字段的首字母没有大写,被认为是未导出的字段,我们不能隐式赋值给未导出的字段,因此不能通过位置初始化进行赋值。

综上所述,由于无法通过 位置初始化 的方式去声明这个结构体的变量,我们只能通过 零值初始化具名字段初始化 的方式去声明结构体变量。

小结

通过本文的探讨,我们了解了在 Go 语言中结构体字段命名使用下划线(_)的特殊用途。

具体来说,定义一个名为 _ 的字段可以有效地强制开发者在初始化结构体时使用具名字段初始化,而不是位置初始化。这样做的好处包括:

  • 代码可读性:具名字段初始化使得代码更具可读性和可维护性,因为每个字段的值都显式地与字段名关联。
  • 避免错误:位置初始化需要严格遵循字段顺序,容易引入错误。具名字段初始化则避免了这一问题。


转载来源:https://juejin.cn/post/7383342927508652083

相关文章
|
4月前
|
Go
Go语言的匿名字段
Go语言支持一种特殊的字段只需要提供类型而不需要写字段名的字段,称之为匿名字段或者嵌套字段。
184 37
Go语言的匿名字段
|
2月前
|
安全 Go
Go语言的iota关键字有什么用途?
在Go语言中, `iota` 是一个特殊常量生成器, 用于在 `const` 声明中创建递增的常量值。每当遇到新的 `const` 关键字时, `iota` 会重置为0并在每个常量声明行上递增1。这非常适合定义枚举类型或一组相关常量。`iota` 大大简化了枚举类型的定义过程, 并提供了类型安全的方法来表示固定值集合, 对于错误码、状态码等非常有用。
|
2月前
|
安全 Go
Go语言的iota关键字有什么用途?
**Go语言中的`iota`是常量生成器,用于在`const`声明中创建递增的常量。`iota`在每个新的`const`块重置为0,然后逐行递增,简化了枚举类型或常量序列的定义。例如,定义星期枚举:** ```markdown ```go type Weekday int const ( Sunday Weekday = iota // 0 Monday // 1 Tuesday // 2 ... ) ``` 同样,`iota`可用于定义不同组的常量,如状态码和标志位,保持各自组内的递增,提高代码可读性。
|
4月前
|
存储 Go
Go 语言用途
Go 语言用途
51 3
|
4月前
|
Cloud Native Linux Go
Go 编程语言详解:用途、特性、与 Python 和 C++ 的比较
Go是一个跨平台、开源的编程语言 Go可用于创建高性能应用程序 Go是一种快速、静态类型、编译型语言,感觉上像动态类型、解释型语言 Go由Robert Griesemer、Rob Pike和Ken Thompson于2007年在Google开发 Go的语法类似于C ++
108 0
|
存储 Go
go语言中空struct{}的用途
在Go语言中,空的 `struct{}` 类型通常被用作占位符或者信号。它不占用任何内存空间,也不包含任何字段,因此它被用来表示一个没有任何数据的结构体。
87 2
|
NoSQL Go MongoDB
go mongodb 忽略字段,go bson 忽略字段
go mongodb 忽略字段,go bson 忽略字段
1126 0
|
Go
Go 通过结构体指定字段进行排序
Go 通过结构体指定字段进行排序
388 0
Go 通过结构体指定字段进行排序
|
JSON API Go
go语言实现调用阿里云api,获取hostname和ip字段值,输出exl表
go语言实现调用阿里云api,获取hostname和ip字段值,输出exl表
276 0
go语言实现调用阿里云api,获取hostname和ip字段值,输出exl表
|
Go
go的继承:匿名字段
go的继承:匿名字段
102 0