内嵌结构体初始化零基础入门指南

简介: 内嵌结构体初始化零基础入门指南

/ Go 语言初始化内嵌结构体的技巧 /


 

一、概述

在 Go 语言中,经常会使用一个结构体内嵌另一个结构体,从而实现代码复用和扩展。但是初始化内嵌结构体也需要技巧,否则可能会引发一些问题。本文将详细探讨初始化内嵌结构体的各种方法。

主要内容包括:

  • 内嵌结构体语法回顾
  • 默认初始化行为
  • 指定初始化语法
  • 构造函数初始化
  • 初始化内嵌指针
  • 扩展阅读 - 内存布局
  • 初始化顺序及优化
  • 子结构重新分配
  • 匿名字段和初始化
  • 实际应用案例

通过学习这些知识,将能够高效并正确地初始化 Go 语言中的内嵌结构体,避免许多潜在问题。


 

二、内嵌结构体语法回顾

先简单回顾一下 Go 语言中内嵌结构体的语法:

type A struct {
  a int
}
type B struct {
  A // 内嵌结构体A
  b int
}

结构体 B 通过内嵌 A 后,就获得了 A 的字段和方法。这实现了类似继承的代码复用。


 

三、默认初始化行为

如果不特别指定,内嵌的结构体也会使用其类型的默认初始化:

type A struct {
  num int
  name string
}
type B struct {
  A
}
func main() {
  var b B
  // b.A是默认初始化的零值
}

这点需要注意,默认初始化可能不是期望的结果。


 

四、指定初始化语法

可以通过指定嵌套的成员名称来初始化:

type A struct {
  num int
}
type B struct {
  A
}
func main() {
  b := B{
    A: A{num: 1},
  }
  // b.A被显式初始化
}

或者对匿名内嵌字段直接初始化:

b := B{
  A{1},
}

这样就可以确保内嵌结构体初始化为所需值。


 

五、构造函数初始化

常会提供一个构造函数来初始化结构:

type A struct {
  num int
}
func NewA(n int) A {
  return A{num: n} 
}
type B struct {
  A
}
func main() {
  b := B{
    A: NewA(1),
  }
  //通过构造函数初始化
}

构造函数可以将初始化集中到一处,并提供必要的初始化逻辑。


 

六、初始化内嵌指针

如果内嵌的是一个指针:

type A struct {
  name string
}
type B struct {
  *A
}

那么就需要显示初始化内嵌指针:

b := B{
  A: &A{"John"},
}

不初始化就会造成空指针异常。


 

七、扩展阅读 - 内存布局

理解内嵌结构体的内存布局也有助于初始化:

type A struct {
  a int
  b int
}
type B struct {
  A
  c int
  d int 
}
// B内存布局
B {
  A.a 
  A.b
  c
  d
}

内嵌后的 A 对象依次放在 B 对象内存布局中。


 

八、初始化顺序及优化

正确的初始化顺序也很重要:

type A struct {
  name string
}
type B struct {
  A
  // 初始化A需要用到B的字段
  firstName string 
}
func NewB() B {
  return B {
    firstName: "John",
    A: A{name: "John"},
  }
}

构造函数可以控制初始化顺序,使之符合依赖关系。

如果可以,建议内嵌结构体放在字段列表开头,以优化内存布局。


 

九、子结构重新分配

有时候需要重新分配内嵌的子结构:

type A struct {
  name string
}
type B struct {
  A
}
func (b *B) Rename(newName string) {
  // 重新分配一个A对象
  b.A = A{name: newName} 
}

这在需要修改内嵌对象时很有用。


 

十、匿名字段和初始化

对于匿名内嵌字段,可以直接初始化:

type A struct {
  name string
}
type B struct {
  A // 内嵌匿名A
}
func main() {
  b := B{
    A: A{name: "Tom"},
  }
  // 等价简写
  b = B{
    A{"Tom"},
  }
}

匿名字段可以直接初始化,无需指定字段名。


 

十一、实际应用案例

来看一个实际的例子,一个用户结构体内嵌了地址结构体:

type Address struct {
  Province string
  City string
}
type User struct {
  Name string
  Age int
  Address 
}
func NewUser(name string, age int, addr Address) User {
  return User{
    Name: name,
    Age: age,
    Address: addr,
  }
}
func main() {
  addr := Address{
    Province: "BJ",
    City: "Beijing",
  }
  u := NewUser("Tom", 20, addr)
}

通过构造函数可以确保初始化顺序正确,不同的结构也可以通过内嵌组合在一起使用。


 

十二、总结

Go 语言中合理初始化内嵌结构体非常重要,需要注意初始化语法、顺序、依赖关系等问题。

通过构造函数、显示初始化、修改子结构等技巧可以正确高效地初始化内嵌的结构体。这是使用内嵌的基础,希望本文可以提供一些参考帮助。


目录
相关文章
|
缓存 安全 Java
JDK8线程池BUG引发的思考
JDK8线程池BUG引发的思考
307 0
|
开发工具 对象存储
nfs挂载报错问题
nfs挂载报错问题
239 0
|
存储 监控 Linux
【Shell 命令集合 系统管理 】⭐⭐⭐Linux 查看当前正在运行的进程信息 ps命令 使用指南
【Shell 命令集合 系统管理 】⭐⭐⭐Linux 查看当前正在运行的进程信息 ps命令 使用指南
439 0
|
8月前
|
人工智能 自然语言处理 搜索推荐
AI对话像真人!交交:上海交大推出全球首个口语对话情感大模型,支持多语言与实时音色克隆
上海交通大学推出的交交是全球首个纯学术界自研的口语对话情感大模型,具备多语言交流、方言理解、角色扮演和情感互动等能力,通过创新技术实现端到端语音对话和实时音色克隆。
753 14
AI对话像真人!交交:上海交大推出全球首个口语对话情感大模型,支持多语言与实时音色克隆
|
运维 负载均衡 监控
如何设计一个高可用的分布式系统?
如何设计一个高可用的分布式系统?
|
存储 弹性计算 数据处理
【云故事探索】NO.6:云端生物,自服务用云的溯源精微
简介: 在北京溯源精微科技有限公司的故事里,云计算成为了驱动生物科技革新的核心力量。自2011年成立以来,溯源精微深耕生物信息分析领域,利用自主研发的BinBash科学计算平台及阿里云的弹性计算与存储解决方案,成功克服了数据处理上的瓶颈。通过与阿里云的合作,公司实现了大规模数据的高效处理,将原本耗时数月的任务缩短至几天乃至几小时。此外,灵活的资源调配能力和按需付费模式极大地降低了计算成本,使溯源精微得以提供精准高效的基因组分析服务。展望未来,溯源精微将继续深化与阿里云的合作,推动生物科技领域智能化发展,携手行业伙伴共创辉煌。
|
自然语言处理 人机交互 API
FunAudioLLM技术测评报告
FunAudioLLM技术测评报告
295 1
I/O设备与主机信息传送的方式(程序查询方式,程序中断方式,DMA方式)
I/O设备与主机信息传送的方式(程序查询方式,程序中断方式,DMA方式
1647 0
|
存储 开发框架 算法
【自己动手画CPU】控制器设计(二)
作者深入探讨了自制CPU的控制器设计,为自学者提供了宝贵的实践指导。文章详细介绍了控制器的设计原理与关键步骤,涵盖了寄存器的配置、指令的执行以及时序控制等方面内容。通过图文并茂的演示,读者可以清晰了解如何从零开始搭建一个基本的控制器,并使其能够执行简单的指令。作者以通俗易懂的方式呈现技术细节,使初学者能够轻松理解和模仿。
1503 0
【自己动手画CPU】控制器设计(二)
|
Oracle 关系型数据库 数据安全/隐私保护
如何选择适合企业的ERP系统
如何选择适合企业的ERP系统
384 0