go语言中的结构体嵌入详解(最新推荐)

 更新时间:2025年12月31日 09:11:50   作者:半桶水专家  
结构体嵌入是Go语言中的一种特性,允许在一个结构体中包含另一个结构体,从而实现代码复用和方法复用,嵌入结构体的字段和方法会被提升到外部结构体中,可以直接访问,本文给大家介绍go语言中的结构体嵌入的相关知识,感兴趣的朋友跟随小编一起看看吧

一、什么是结构体嵌入?

结构体嵌入 = 在一个结构体中,直接写另一个结构体类型,不写字段名

type Base struct {
	ID   int
	Name string
}
type User struct {
	Base   // 嵌入结构体(匿名字段)
	Age int
}

等价于(语义上):

type User struct {
	Base Base
	Age  int
}

但用法和能力完全不同(这是重点)。

二、最直观的效果:字段“提升”(Promoted Fields)

1️⃣ 直接访问被嵌入结构体的字段

u := User{
	Base: Base{
		ID:   1,
		Name: "Tom",
	},
	Age: 18,
}
fmt.Println(u.ID)        // 1
fmt.Println(u.Name)      // Tom
fmt.Println(u.Base.ID)   // 1(也可以)

👉 Base 的字段被“提升”到了 User 上

三、方法也会被“提升”(非常关键)

1️⃣ 嵌入结构体的方法

type Base struct{}
func (b Base) Hello() {
	fmt.Println("hello from Base")
}
type User struct {
	Base
}
var u User 
u.Hello() // 等价于 u.Base.Hello()

📌 字段 + 方法都会被提升

四、结构体嵌入 ≠ 继承,但很像

Go 没有 extends,但结构体嵌入提供了:

能力Go 结构体嵌入
代码复用
方法复用
多继承✅(可嵌入多个)
父子类型关系❌(不是 is-a)

五、嵌入多个结构体(类似多继承)

type Logger struct{}
func (l Logger) Log() { fmt.Println("log") }
type Auth struct{}
func (a Auth) Check() { fmt.Println("auth") }
type Service struct {
	Logger
	Auth
}
s := Service{}
s.Log()
s.Check()

👉 Go 允许多个嵌入结构体

六、字段 / 方法冲突规则(必考点)

1️⃣ 同名字段冲突

type A struct {
	Name string
}
type B struct {
	Name string
}
type C struct {
	A
	B
}

❌ 不能直接:

c.Name // 编译错误:ambiguous selector

✅ 必须显式指定:

c.A.Name 
c.B.Name

2️⃣ 子结构体“覆盖”嵌入结构体字段

type Base struct {
	Name string
}
type User struct {
	Base
	Name string
}
u := User{}
u.Name = "UserName"      // 访问的是 User.Name
u.Base.Name = "BaseName"

📌 就近原则:优先访问最外层字段

七、值嵌入 vs 指针嵌入(非常重要)

1️⃣ 值嵌入

type User struct {
	Base
}
  • 拷贝一份 Base
  • 修改时改的是副本

2️⃣ 指针嵌入(推荐)

type User struct {
	*Base
}
b := &Base{ID: 1}
u := User{Base: b}
u.ID = 2
fmt.Println(b.ID) // 2

共享同一份数据
✅ 常用于组合、组件设计

八、嵌入结构体与接口的“神级配合”

这是 Go 非常核心的设计思想。

1️⃣ 嵌入结构体自动“继承”接口实现

type Speaker interface {
	Speak()
}
type Human struct{}
func (h Human) Speak() {
	fmt.Println("human speak")
}
type Student struct {
	Human
}
var s Speaker = Student{} // ✅ Student 自动实现 Speaker
s.Speak()

📌 只要嵌入的结构体实现了接口,外层结构体也实现了接口

九、嵌入基础类型(不常用但要知道)

type MyInt int
type Counter struct {
	MyInt
}
c := Counter{}
c.MyInt = 10

⚠️ 不如结构体嵌入常见,但合法

十、结构体嵌入 vs 普通字段 对比

对比项嵌入结构体普通字段
访问方式u.IDu.Base.ID
方法提升
接口继承
语义组合拥有

📌 推荐原则
👉 想复用行为(方法) → 用嵌入
👉 只是数据成员 → 用普通字段

十一、工程实践中的典型用法

1️⃣ Web / 业务模型

type Model struct {
	ID        uint
	CreatedAt time.Time
	UpdatedAt time.Time
}
type Order struct {
	Model
	OrderNo string
}

(GORM 就大量用这个模式)

2️⃣ 装饰 / 组合模式

type Service struct {
	*Logger
	*DB
}

十二、常见坑总结 ⚠️

  • 以为是继承(不是)
  • ❌ 字段冲突没处理
  • ❌ 不理解指针嵌入 vs 值嵌入
  • ❌ 滥用嵌入(嵌太多层可读性差)

到此这篇关于go语言中的结构体嵌入详解的文章就介绍到这了,更多相关go语言结构体嵌入内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • golang时间、时区、格式的使用方法

    golang时间、时区、格式的使用方法

    这篇文章主要介绍了golang时间、时区、格式的使用方法,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-04-04
  • Golang中的闭包(Closures)详解

    Golang中的闭包(Closures)详解

    在 Golang 中,闭包是一个引用了作用域之外的变量的函数,Golang 中的匿名函数也被称为闭包,闭包可以被认为是一种特殊类型的匿名函数,所以本文就给大家详细的介绍一下Golang的闭包到底是什么,感兴趣的小伙伴跟着小编一起来看看吧
    2023-07-07
  • sync.WaitGroup的用法及说明

    sync.WaitGroup的用法及说明

    Go语言中WaitGroup用于同步goroutine,Add设置计数器,Done减1,Wait阻塞直到计数器归零,示例显示并发执行结果顺序随机,但整体完成后输出over
    2025-07-07
  • Go语言之init函数

    Go语言之init函数

    Go语言有一个特殊的函数init,先于main函数执行,实现包级别的一些初始化操作。这篇文章介绍了Go中的Init函数,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-07-07
  • go语言import报错处理图文详解

    go语言import报错处理图文详解

    今天本来想尝试一下go语言中公有和私有的方法,结果import其他包的时候直接报错了,下面这篇文章主要给大家介绍了关于go语言import报错处理的相关资料,需要的朋友可以参考下
    2023-04-04
  • Golang时间及时间戳的获取转换超全面详细讲解

    Golang时间及时间戳的获取转换超全面详细讲解

    说实话,golang的时间转化还是很麻烦的,最起码比php麻烦很多,下面这篇文章主要给大家介绍了关于golang时间/时间戳的获取与转换的相关资料,文中通过实例代码介绍的非常详细,需要的朋友可以参考下
    2022-12-12
  • 浅析Go使用定时器时如何避免潜在的内存泄漏陷阱

    浅析Go使用定时器时如何避免潜在的内存泄漏陷阱

    这篇文章来和大家一起探讨一下Go 中如何高效使用 timer,特别是与select 一起使用时,如何防止潜在的内存泄漏问题,感兴趣的可以了解下
    2024-01-01
  • Go语言中Redis缓存与本地内存缓存实战

    Go语言中Redis缓存与本地内存缓存实战

    在现代高并发系统中,缓存技术是提升性能和降低数据库压力的关键手段,本文将为大家介绍一下Redis缓存与本地内存缓存的具体应用,需要的可以了解下
    2025-03-03
  • Golang实现自己的orm框架实例探索

    Golang实现自己的orm框架实例探索

    这篇文章主要为大家介绍了Golang实现自己的orm框架实例探索,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01
  • Golang中的int类型和uint类型到底有多大?

    Golang中的int类型和uint类型到底有多大?

    int和uint类型在我们日常开发中经常会用到,但有个疑问就是这两个类型有多大,通过各种尝试最终得到了答案,所以下面这篇文章主要给大家介绍了关于Golang中的int类型和uint类型到底有多大的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下。
    2017-12-12

最新评论