iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > GO >Golang如何实现不被复制的结构体
  • 162
分享到

Golang如何实现不被复制的结构体

2023-07-05 19:07:30 162人浏览 独家记忆
摘要

这篇文章主要介绍“golang如何实现不被复制的结构体”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Golang如何实现不被复制的结构体”文章能帮助大家解决问题。不允许复制的结构体sync包中的许多

这篇文章主要介绍“golang如何实现不被复制的结构体”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Golang如何实现不被复制的结构体”文章能帮助大家解决问题。

不允许复制的结构体

sync包中的许多结构都是不允许拷贝的,比如sync.Cond,sync.WaitGroup,sync.Pool, 以及sync包中的各种,因为它们自身存储了一些状态(比如等待者的数量),如果你尝试复制这些结构体:

var wg1 sync.WaitGroupwg2 := wg1 // 将 wg1 复制一份,命名为 wg2// ...

那么你将在你的 IDE 中看到一个醒目的警告:

assignment copies lock value to wg2: sync.WaitGroup contains sync.noCopy

IDE是如何实现这一点的呢?我们自己又能否利用这一机制来告诉别人,不要拷贝某个结构体呢?

(懒得看原理,只想知道怎么用,可以直接下划至结论部分)

实现原理

大部分编辑器/IDE都会在你的代码上运行go vet,vet是Go官方提供的静态分析工具,我们刚刚得到的提示信息就是vet分析代码后告诉我们的。vet的实现在Go源码cmd/vet中,里面注册了很多不同类型的分析器,其中copylock这个分析器会检查实现了LockUnlock方法的结构体是否被复制。

copylock Analysercmd/vet中注册,具体实现代码在golang.org/x/tools/go/analysis/passes/copylock/copylock.go中, 这里只摘抄部分核心代码进行解释:

var lockerType *types.Interfacefunc init() {    //...    methods := []*types.Func{        types.NewFunc(token.NoPos, nil, "Lock", nullary),        types.NewFunc(token.NoPos, nil, "Unlock", nullary),    }    // Locker 结构包括了 Lock 和 Unlock 两个方法    lockerType = types.NewInterface(methods, nil).Complete()}

init函数中把包级别的全局变量lockerType进行了初始化,lockerType内包含了两个方法: LockUnlock, 只有实现了这两个方法的结构体才是copylock Analyzer要处理的对象。

// lockPath 省略了参数部分,只保留了最核心的逻辑,// 用来检测某个类型是否实现了Locker接口(Lock和Unlock方法)func lockPath(...) typePath {    // ...    // 如果传进来的指针类型实现了Locker接口, 就返回这个类型的信息    if types.Implements(types.NewPointer(typ), lockerType) && !types.Implements(typ, lockerType) {        return []string{typ.String()}    }    // ...}

lockPath会检测传入的参数是否实现了LockUnlock方法,如果是则返回类型的信息。而vet会在AST上每个需要检查的节点上调用lockPath函数(如赋值、函数调用等场景)。如果在这些会导致复制的场景中,发现了锁结构体的复制,则会报告给用户:

func run(pass *analysis.Pass) (interface{}, error) {    // ...    // 需要检查的节点    switch node := node.(type) {    // range语句    case *ast.RangeStmt:        checkCopyLocksRange(pass, node)    // 函数声明    case *ast.FuncDecl:        checkCopyLocksFunc(pass, node.Name.Name, node.Recv, node.Type)    // 函数字面量(匿名函数)    case *ast.FuncLit:        checkCopyLocksFunc(pass, "func", nil, node.Type)    // 调用表达式(Foo(xxx))    case *ast.CallExpr:        checkCopyLocksCallExpr(pass, node)    // 赋值语句    case *ast.AssignStmt:        checkCopyLocksAssign(pass, node)    // 通用声明(import/const/type/var)    case *ast.GenDecl:        checkCopyLocksGenDecl(pass, node)    // 复合常量({a,b,c})    case *ast.CompositeLit:        checkCopyLocksCompositeLit(pass, node)    // return语句    case *ast.ReturnStmt:        checkCopyLocksReturnStmt(pass, node)    // ...}// checkCopyLocksAssign 检查赋值操作是否复制了一个锁func checkCopyLocksAssign(pass *analysis.Pass, as *ast.AssignStmt) {    for i, x := range as.Rhs {        // 如果等号右边的结构体里有字段实现了Lock/Unlock的话,就输出警告信息        if path := lockPathRhs(pass, x); path != nil {            pass.ReportRangef(x, "assignment copies lock value to %v: %v", analysisutil.FORMat(pass.Fset, as.Lhs[i]), path)        }    }}

上面只列出了赋值操作的实现代码,其它类型的检查这里就不一一解释了,感兴趣的同学可以自行查看源码。

结论

只要你的IDE会帮你运行go vet(目前主流的vscode和GoLand都会自动帮你运行),你就能通过这个机制来提醒他人,尽量避免复制结构体。

如果你的结构体也因为某些原因,不希望使用者复制,你也可以使用该机制来警告使用者:

定义一个实现了LockUnlock的结构体

type noCopy struct{}func (*noCopy) Lock()   {}func (*noCopy) Unlock() {}

将其放入你的结构体中:

// Foo 代表你不希望别人复制的结构体type Foo struct {    noCopy noCopy    // ...}

或直接让你的结构体实现LockUnlock方法:

type Foo struct {    // ...}func (*Foo) Lock()   {}func (*Foo) Unlock() {}

这样别人在尝试复制Foo的时候,就会得到IDE的警告信息了。

关于“Golang如何实现不被复制的结构体”的内容就介绍到这里了,感谢大家的阅读。如果想了解更多行业相关的知识,可以关注编程网GO频道,小编每天都会为大家更新不同的知识点。

您可能感兴趣的文档:

--结束END--

本文标题: Golang如何实现不被复制的结构体

本文链接: https://www.lsjlt.com/news/354914.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Golang如何实现不被复制的结构体
    这篇文章主要介绍“Golang如何实现不被复制的结构体”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Golang如何实现不被复制的结构体”文章能帮助大家解决问题。不允许复制的结构体sync包中的许多...
    99+
    2023-07-05
  • Golang实现不被复制的结构体的方法
    目录不允许复制的结构体实现原理结论不允许复制的结构体 sync包中的许多结构都是不允许拷贝的,比如sync.Cond,sync.WaitGroup,sync.Pool, 以及sync...
    99+
    2023-05-14
    Golang不被复制结构体 Golang 复制结构体 Golang 结构体
  • golang 实现两个结构体复制字段
    实际工作中可能会有这样的场景: 两个结构体(可能类型一样), 字段名和类型都一样, 想复制一个结构体的全部或者其中某几个字段的值到另一个(即merge操作), 自然想到可以用反射实现...
    99+
    2024-04-02
  • Golang如何实现Json转结构体
    这篇文章主要讲解了“Golang如何实现Json转结构体”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Golang如何实现Json转结构体”吧!请求Zabbix API,通过itemid获取...
    99+
    2023-07-05
  • 怎么在golang中实现两个结构体复制字段
    怎么在golang中实现两个结构体复制字段?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。golang的优点golang是一种编译语言,可以将代码编译为机器代码,...
    99+
    2023-06-14
  • golang中结构体嵌套接口如何实现
    今天小编给大家分享一下golang中结构体嵌套接口如何实现的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。在golang中结构...
    99+
    2023-07-05
  • golang如何返回结构体?
    如何在 golang 中返回结构体?在函数签名中指定结构体类型,如:func getperson() person {}。在函数体内使用 return {} 语句返回结构体,其中包含所需...
    99+
    2024-04-23
    golang 结构体
  • Golang怎么实现Json转结构体
    这篇文章主要讲解了“Golang怎么实现Json转结构体”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Golang怎么实现Json转结构体”吧!请求Zabbix API,通过itemid获取...
    99+
    2023-07-05
  • linux文件夹复制如何实现目录结构不变
    本篇内容介绍了“linux文件夹复制如何实现目录结构不变”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!在linux中,可以利用cp命令实现赋...
    99+
    2023-07-02
  • Go Struct结构体如何实现
    本文小编为大家详细介绍“Go Struct结构体如何实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“Go Struct结构体如何实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。什么是结构...
    99+
    2023-07-05
  • golang中结构体嵌套接口的实现
    在golang中结构体A嵌套另一个结构体B见的很多,可以扩展A的能力。 A不仅拥有了B的属性,还拥有了B的方法,这里面还有一个字段提升的概念。 示例: package main i...
    99+
    2023-05-14
    golang 结构体嵌套接口 golang 嵌套接口
  • golang结构体序列化怎么实现
    在Go中,可以使用encoding/json包来实现结构体的序列化和反序列化。 首先,需要导入encoding/json包: imp...
    99+
    2023-10-22
    golang
  • 实例分析:如何在Golang中实现高效的结构体强转
    对于一个Golang开发者来说,牢固扎实的基础是十分重要的,编程网就来带大家一点点的掌握基础知识点。今天本篇文章带大家了解《实例分析:如何在Golang中实现高效的结构体强转》,主要介绍了,希望对大...
    99+
    2024-04-05
  • Golang实现Json转结构体的示例详解
    解决实际需求,案例分享。 1.请求Zabbix API,通过itemid获取到AppName(应用集名称) package main import (  "encoding/jso...
    99+
    2023-02-19
    Golang Json转结构体 Golang Json 结构体
  • GoStruct结构体的具体实现
    目录什么是结构体1. 基本实例化(方法1)2. new实例化(方法2)3. 键值对初始化(方法3 结构体能够使用指针就使用指针)结构体方法和接收者encoding-json包1. s...
    99+
    2023-03-15
    Go Struct结构体 Go Struct
  • c# 如何使用结构体实现共用体
    目录理解 C 语言的共用体使用 C# 实现共用体共用体作为另一个共用体的成员在 C 和 C# 编程语言中,结构体(Struct)是值类型数据结构,它使得一个单一变量可以存储多种类型的...
    99+
    2024-04-02
  • Golang如何实现数据结构Stack
    本文小编为大家详细介绍“Golang如何实现数据结构Stack”,内容详细,步骤清晰,细节处理妥当,希望这篇“Golang如何实现数据结构Stack”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。介绍Stack在计...
    99+
    2023-07-06
  • 如何理解 Golang 结构体中的切片
    在Golang中,结构体是一种自定义的数据类型,它可以包含多个字段。而在结构体中,切片是一种动态数组,可以根据需要进行扩容或缩小。然而,理解Golang结构体中的切片可能会引起一些困惑...
    99+
    2024-02-08
    golang开发
  • 如何用python实现结构体数组
    目录python结构体数组在NumPy中可以如下定义内存对齐python自定义结构体具体方法如下python结构体数组 在C语言中我们可以通过struct关键字定义结构类型,结构中的...
    99+
    2024-04-02
  • Golang如何实现一个不可复制类型
    这篇文章主要讲解了“Golang如何实现一个不可复制类型”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“Golang如何实现一个不可复制类型”吧!如何复制一个对象不考虑IDE提供的代码分析和g...
    99+
    2023-07-05
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作