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

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

/ 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 语言中合理初始化内嵌结构体非常重要,需要注意初始化语法、顺序、依赖关系等问题。

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


目录
相关文章
|
7月前
|
C++
C++系列十四:结构体
C++系列十四:结构体
|
Go
Go语言初始化指南:结构体成员变量的正确方式
Go语言初始化指南:结构体成员变量的正确方式
247 0
|
2月前
|
存储 C语言
C语言:一维数组的不初始化、部分初始化、完全初始化的不同点
C语言中一维数组的初始化有三种情况:不初始化时,数组元素的值是随机的;部分初始化时,未指定的元素会被自动赋值为0;完全初始化时,所有元素都被赋予了初始值。
|
3月前
|
前端开发 JavaScript
前端基础(九)_this基本使用、this指向判断、改变this指向的方法
本文介绍了JavaScript中this的基本使用、this指向的判断以及改变this指向的方法。
55 1
前端基础(九)_this基本使用、this指向判断、改变this指向的方法
|
6月前
|
编译器 C语言 C++
结构体的详解(想要彻底了解结构体,那么看这一篇就够了!)
结构体的详解(想要彻底了解结构体,那么看这一篇就够了!)
|
7月前
|
安全 编译器 C++
【C/C++ 基础知识 】 C++ 初始化大全:选择最适合您需求的方式
【C/C++ 基础知识 】 C++ 初始化大全:选择最适合您需求的方式
164 2
|
7月前
|
存储 编译器 Go
Go 语言数组基础教程 - 数组的声明、初始化和使用方法
数组用于在单个变量中存储相同类型的多个值,而不是为每个值声明单独的变量。 声明数组 在Go中,有两种声明数组的方式:
169 0
|
存储 安全 编译器
【C++杂货铺】C++11特性总结:列表初始化 | 声明 | STL的升级
【C++杂货铺】C++11特性总结:列表初始化 | 声明 | STL的升级
83 0
|
前端开发
前端学习案例4-类组件中绑定this指向的方式
前端学习案例4-类组件中绑定this指向的方式
73 0
前端学习案例4-类组件中绑定this指向的方式
指针介绍及使用方法
指针介绍及使用方法
149 0