golang中具有 “no copy“的类型

embedded/2025/3/14 4:15:24/

在 Go 语言中,某些类型由于特殊用途或底层实现,可能会被标记为 “no copy”,即它们不能被复制,通常是因为复制会导致意外的行为或错误。这些类型主要包括:


1. sync.Mutexsync.RWMutex

  • 原因:Mutex 是用于同步的锁,复制后可能会导致多个实例操作同一个底层锁的情况,从而引发竞争条件或死锁。
  • 示例
    var mu sync.Mutex
    copyMu := mu // ❌ 错误,拷贝 Mutex 会导致不可预测行为
    

2. sync.Cond

  • 原因sync.Cond 依赖于 sync.Mutex,如果复制,会导致多个 Cond 变量竞争同一个锁。
  • 示例
    var cond = sync.NewCond(&sync.Mutex{})
    copyCond := *cond // ❌ 不应该复制
    

3. sync.Once

  • 原因sync.Once 用于确保某段代码只执行一次,复制 Once 可能导致相同的初始化逻辑执行多次。
  • 示例
    var once sync.Once
    copyOnce := once // ❌ 拷贝可能会导致 `Do` 不能正确保证只执行一次
    

4. sync.WaitGroup

  • 原因sync.WaitGroup 维护一个内部计数器,拷贝后多个 WaitGroup 可能操作同一个计数器,导致错误。
  • 示例
    var wg sync.WaitGroup
    copyWg := wg // ❌ 复制 WaitGroup 可能导致等待逻辑混乱
    

5. sync.Pool

  • 原因sync.Pool 是一个对象池,拷贝会导致多个 Pool 可能共享相同的对象存储区,破坏内存管理。
  • 示例
    var pool sync.Pool
    copyPool := pool // ❌ 复制可能导致多个 Pool 共享底层存储,导致数据混乱
    

6. context.Context(通常不应该被复制)

  • 原因context.Context 用于控制超时、取消等,复制 Context 可能会导致取消信号不生效。
  • 示例
    ctx := context.Background()
    copyCtx := ctx // ❌ 复制 context 可能导致错误的取消行为
    

7. runtime/internal/atomic.NoCopy 结构体的类型

  • Go 内部提供了 runtime/internal/atomic.NoCopy 结构体,嵌入该类型的结构体会在 go vet 检查时报错,防止误复制。
  • 示例
    type myStruct struct {noCopy runtime/internal/atomic.NoCopy
    }
    

如何防止结构体被拷贝?

如果你定义的结构体不希望被复制,可以嵌入 sync.NoCopy(Go 1.20 之后正式提供):

import "sync"type MyStruct struct {noCopy sync.NoCopy
}

这样,go vet 工具会在发现 MyStruct 被复制时发出警告。


总结

在 Go 语言中,以下类型通常不能被复制:

  • 同步相关
    • sync.Mutex
    • sync.RWMutex
    • sync.Cond
    • sync.Once
    • sync.WaitGroup
    • sync.Pool
  • 上下文管理
    • context.Context
  • 使用 sync.NoCopyruntime/internal/atomic.NoCopy 防止拷贝的结构体

一般来说,如果一个类型涉及 锁、并发同步、状态管理,就要特别注意 避免拷贝,否则可能会导致竞态条件、锁丢失或不一致行为。


http://www.ppmy.cn/embedded/172411.html

相关文章

Node.js学习分享(下)

Node.js Expressexpress的基本用法创建基本的web服务器监听GET请求监听POST请求把内容响应给客户端获取URL中携带的查询参数获取URL中的动态参数 托管静态资源express.static()托管多个静态资源目录挂载路径前缀 Express路由路由模块化 Express中间件Express中间件的调用流程Ex…

C++零基础LeetCode热题100- 128.最长连续序列

128.最长连续序列 题目描述思路步骤实现代码代码详解提交结果注意 题目描述 给定一个未排序的整数数组 nums ,找出数字连续的最长序列(不要求序列元素在原数组中连续)的长度。 请你设计并实现时间复杂度为 O(n) 的算法解决此问题。 思路 …

使用curl库编写爬虫程序的指令抓取优质视频

首先,curl本身是一个命令行工具,用来传输数据,支持多种协议,包括HTTP、HTTPS等。用户提到“使用curl库编写爬虫程序”,可能指的是用libcurl库在编程语言中调用,比如Python的pycurl,或者C/C直接使…

PHP前后开发纪录

一.LayUI相关 在LayUI中使用jquery读取本地json文件: // getJSON为直接读取本地文件,要改成调接口$.getJSON(/datafile/enviro-factory.json,function(data){data.forEach(element > {setMarkerLabel(element,T,map)});// setMarkerLabel(data[0],T,map)});二.p…

[Python爬虫系列]bilibili

[Python爬虫系列]bilibili 具体逻辑 bv号 -> 处理多P视频 -> 拿到cid -> sign -> 请求下载,其中sign参考前人算法(https://github.com/SocialSisterYi/bilibili-API-collect) b站视频下载链接 https://api.bilibili.com/x/pl…

EXCEL IF自动填充功能

使用Excel自动填充端口用途:提升工作效率的技巧 在日常工作中,Excel 是一个非常强大的工具,尤其是在处理大量数据时。通过使用 Excel 的自动填充功能,我们可以快速地为数据添加额外的信息,从而提升工作效率。本文将介…

Redis 6.2.7安装配置

Redis-6.2.7下载 下载地址:https://download.redis.io/releases/redis-6.2.7.tar.gz 解压缩文件 tar -zxvf redis-6.0.3.tar.gz 安装gcc yum install gcc 进入压缩包src目录下进行源码编译,将redis安装到/usr/local/redis目录下 cd /opt/software/red…

Flutter 基础组件 Image 详解

目录 1. 引言 2. 加载图片的方式 2.1 本地图片 2.2 网络图片 2.3 本地文件图片 2.4 内存图片 3. fit 参数:控制图片适应方式 4. 高级应用技巧 4.1 占位符与淡入效果 4.2 图片缓存管理 4.3 图片裁剪与滤镜 5. 性能优化指南 5.1 资源图片规范 2. 大图加…