讲师中心 微信公众号
AI工具推荐 视频效率加速

如何在 Go 中正确选择嵌入结构体时使用值还是指针

老墨小哥_6775

老墨小哥_6775

发布时间:2026-01-05 12:58:02

|

994人浏览过

|

来源于php中文网

原创

如何在 Go 中正确选择嵌入结构体时使用值还是指针

在 go 中嵌入结构体时,应根据是否需要共享状态、避免拷贝开销或支持运行时动态替换来决定使用值嵌入还是指针嵌入;`log.logger` 等非接口类型两者皆可,但指针嵌入更灵活、更符合常见实践。

Go 的嵌入(embedding)机制是实现组合与方法提升(method promotion)的核心特性。当你将一个类型作为匿名字段嵌入到另一个结构体中时,该类型的方法会自动提升为外层结构体的方法——但这一机制对嵌入类型的形态有明确限制:根据 Go 语言规范,嵌入字段必须是*具名类型 T 或其指针 `T**,且T不能是指针类型(即不支持*T或interface{})。由于log.Logger` 是一个具体结构体(非接口),因此以下两种写法在语法和语义上均合法:

// ✅ 合法:嵌入值(拷贝语义)
type Job struct {
    Command string
    log.Logger // 值嵌入
}

// ✅ 合法:嵌入指针(引用语义)
type Job struct {
    Command string
    *log.Logger // 指针嵌入
}

然而,语义差异显著:

  • 值嵌入(log.Logger):每次创建 Job 实例时,都会完整拷贝一份 Logger 内部状态(如 mu sync.Mutex, out io.Writer, prefix, flag 等)。这不仅带来不必要的内存开销,还可能导致并发安全问题(如多个 Job 实例各自持有独立的 Mutex,无法协同保护共享资源)。

  • *指针嵌入(`log.Logger)**:所有Job实例可共享同一个Logger实例,方法调用直接作用于原始对象;支持运行时动态重绑定(job.Logger = anotherLogger`),天然适配 Flyweight 模式,大幅提升内存效率与设计灵活性。

    使用Go语言搭建家庭相册系统-相关课件
    使用Go语言搭建家庭相册系统-相关课件

    使用Go语言搭建家庭相册系统-相关课件

    下载

例如,考虑如下典型场景:

type Bitmap struct {
    data [4][5]bool
}

type Renderer struct {
    *Bitmap // 指针嵌入,支持共享底层数据
    on, off byte
}

func (r *Renderer) render() {
    for _, row := range r.data {
        for _, bit := range row {
            if bit {
                fmt.Print(string(r.on))
            } else {
                fmt.Print(string(r.off))
            }
        }
        fmt.Println()
    }
}

// 共享同一 Bitmap 实例
var pic Bitmap
pic.data[0][0] = true
pic.data[1][1] = true

renderA, renderB := Renderer{on: 'X', off: 'O'}, Renderer{on: '@', off: '.'}
renderA.Bitmap = &pic // 动态绑定
renderB.Bitmap = &pic // 同一底层数组

renderA.render() // 输出含 X/O 的图案
renderB.render() // 输出含 @/. 的同一图案(不同字符映射)

✅ 推荐实践:

  • 优先使用 *T 指针嵌入,尤其当 T 包含同步原语(如 sync.Mutex)、大字段或需跨实例共享状态时;
  • 若 T 是小而无状态的纯数据结构(如 type Point struct{ X, Y int }),且明确需要隔离副本,可考虑值嵌入;
  • *永远不要嵌入 `interface{}或T`:它们不携带方法集,违背嵌入的设计初衷(方法提升);
  • 初始化时,配合 NewXXX() 工厂函数(返回 *T)自然契合指针嵌入,无需额外取地址操作。

总之,嵌入不是“语法糖”,而是有明确语义责任的设计选择。选择 *log.Logger 而非 log.Logger,不仅是惯用法,更是对可维护性、内存效率与并发安全的主动承诺。

热门AI工具

更多
VibeKnow
VibeKnow Hot

一款AI视频创作工具,主要用于全球首个AI知识视频创作平台,文档、文章、网页,一键生成视频,适合需要提升相关任务效率的用户。

豆包大模型

豆包大模型是一款由字节跳动推出的企业级大语言模型服务平台。

墨刀AI
墨刀AI Hot

一款AI图像与设计工具,主要用于产品经理的专属智能体,适合需要提升相关任务效率的用户。

WorkBuddy

一款AI办公效率工具,主要用于腾讯云推出的AI原生桌面智能体工作台,适合需要提升相关任务效率的用户。

Seko
Seko Hot

一款AI视频创作工具,主要用于商汤科技推出的创编一体的AI短视频创作Agent,适合需要提升相关任务效率的用户。

DeepSeek

DeepSeek是一款面向对话、写作、编程和推理场景的AI大模型工具。

AionClaw
AionClaw Hot

AionClaw是一款面向办公、创作和编程任务的AI桌面智能体。

切问学术

切问学术是一款AI论文写作工具,复旦大学NLP团队推出的AI学术智能体。

讯飞智作

讯飞智作是一款AI视频创作工具,AI文本配音工具,数字人课程、营销视频制作。

相关专题

更多
golang结构体相关大全
golang结构体相关大全

本专题整合了golang结构体相关大全,想了解更多内容,请阅读专题下面的文章。

4014

2025.06.09

golang结构体方法
golang结构体方法

本专题整合了golang结构体相关内容,请阅读专题下面的文章了解更多。

4171

2025.07.04

string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

5279

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2685

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

3288

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

2365

2025.08.29

C++ 智能指针与现代内存管理
C++ 智能指针与现代内存管理

深入讲解 C++ 现代内存管理的核心工具——智能指针,涵盖 unique_ptr 独占所有权语义、shared_ptr 引用计数机制与循环引用问题、weak_ptr 弱引用的应用场景、make_unique/make_shared 工厂函数的性能优势、自定义删除器的编写、RAII 资源管理思想的实践,以及从裸指针迁移到智能指针的重构策略,帮助开发者编写安全无泄漏的现代 C++ 代码。

299

2026.04.23

treenode的用法
treenode的用法

​在计算机编程领域,TreeNode是一种常见的数据结构,通常用于构建树形结构。在不同的编程语言中,TreeNode可能有不同的实现方式和用法,通常用于表示树的节点信息。更多关于treenode相关问题详情请看本专题下面的文章。php中文网欢迎大家前来学习。

2181

2023.12.01

Buffalo框架数据库开发全教程
Buffalo框架数据库开发全教程

本专题围绕Buffalo框架数据库开发,讲解database.yml多环境配置、soda与fizz迁移生成回滚、模型结构体标签、增删改查与条件查询、一对多与多对多关联、数据校验、回调钩子、事务处理及原生SQL执行能力。

80

2026.09.23

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn