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

Golang实现不被复制的结构体的方法

Golang不被复制结构体Golang 复制结构体Golang 结构体 2023-05-14 05:05:25 795人浏览 薄情痞子
摘要

目录不允许复制的结构体实现原理结论不允许复制的结构体 sync包中的许多结构都是不允许拷贝的,比如sync.Cond,sync.WaitGroup,sync.Pool, 以及sync

不允许复制的结构体

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

var wg1 sync.WaitGroup
wg2 := 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.Interface

func 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实现不被复制的结构体的方法的文章就介绍到这了,更多相关Golang结构体内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!

您可能感兴趣的文档:

--结束END--

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

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

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

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

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

下载Word文档
猜你喜欢
  • Golang实现不被复制的结构体的方法
    目录不允许复制的结构体实现原理结论不允许复制的结构体 sync包中的许多结构都是不允许拷贝的,比如sync.Cond,sync.WaitGroup,sync.Pool, 以及sync...
    99+
    2023-05-14
    Golang不被复制结构体 Golang 复制结构体 Golang 结构体
  • Golang如何实现不被复制的结构体
    这篇文章主要介绍“Golang如何实现不被复制的结构体”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Golang如何实现不被复制的结构体”文章能帮助大家解决问题。不允许复制的结构体sync包中的许多...
    99+
    2023-07-05
  • golang 实现两个结构体复制字段
    实际工作中可能会有这样的场景: 两个结构体(可能类型一样), 字段名和类型都一样, 想复制一个结构体的全部或者其中某几个字段的值到另一个(即merge操作), 自然想到可以用反射实现...
    99+
    2022-11-12
  • 怎么在golang中实现两个结构体复制字段
    怎么在golang中实现两个结构体复制字段?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。golang的优点golang是一种编译语言,可以将代码编译为机器代码,...
    99+
    2023-06-14
  • golang中使用匿名结构体的方法
    目录转化为map定义具名结构体定义匿名结构体在一些项目中, 我们会使用json 来将字符串转为结构体,但是很多时候,这种结构体只会用一次,基本上只会用于反序列化, 对于这种只用到一次...
    99+
    2022-11-11
  • golang输出结构体的方法是什么
    在Go语言中,要输出结构体的方法有两种方式:1. 使用fmt包的Println、Printf或Print函数:这些函数可以直接打印出...
    99+
    2023-08-31
    golang
  • mysql表结构的复制方法
    本篇内容主要讲解“mysql表结构的复制方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“mysql表结构的复制方法”吧!我们特别是oracle dbas常常会...
    99+
    2022-10-18
  • golang中结构体嵌套接口的实现
    在golang中结构体A嵌套另一个结构体B见的很多,可以扩展A的能力。 A不仅拥有了B的属性,还拥有了B的方法,这里面还有一个字段提升的概念。 示例: package main i...
    99+
    2023-05-14
    golang 结构体嵌套接口 golang 嵌套接口
  • Golang实现Json转结构体的示例详解
    解决实际需求,案例分享。 1.请求Zabbix API,通过itemid获取到AppName(应用集名称) package main import (  "encoding/jso...
    99+
    2023-02-19
    Golang Json转结构体 Golang Json 结构体
  • Golang函数的算法和数据结构实现方法
    作为一种相对较新的编程语言,Go语言(也通常称为Golang)已被越来越多的开发者所青睐。Golang的一大特点就是速度快,而这是得益于其高效的并发机制和出色的算法实现。在Golang中,函数是非常重要的概念,成为了程序员高效编写代码的关键...
    99+
    2023-05-17
    算法 Golang 数据结构
  • Golang怎么使用gob实现结构体的序列化
    本文小编为大家详细介绍“Golang怎么使用gob实现结构体的序列化”,内容详细,步骤清晰,细节处理妥当,希望这篇“Golang怎么使用gob实现结构体的序列化”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。Gol...
    99+
    2023-07-05
  • c语言结构体字节对齐的实现方法
    目录1.什么是字节对齐 2.为什么要有字节对齐 3.手动设置对齐 4.结构体比较方法 1.什么是字节对齐 在c语言的结构体里面一般会按照某种规则去进行字节对齐。 我们先看一段代码...
    99+
    2022-11-12
  • Golang 利用反射对结构体优雅排序的操作方法
    最近开始实习,工作技术栈主要Python和Golang,目前的任务把Python模块重构为GO模块,然后出现了一个问题,就是要将一个结构体按结构体中各个字段进行排序,然后写入Redi...
    99+
    2022-11-12
  • Golang使用gob实现结构体的序列化过程详解
    目录Gob简介单个对象序列化列表数据序列化简单编码示例编码在TCP连接中使用Golang有自己的序列化格式,称为gob。使用gob可以对结构进行编码和解码。你可以使用其他格式,如JS...
    99+
    2023-03-08
    Golang序列化结构体 Golang gob序列化
  • go结构体强制类型转换的方法是什么
    在Go语言中,结构体之间的强制类型转换需要使用类型断言。类型断言的语法如下:```govalue, ok := expression...
    99+
    2023-08-08
    go
  • html5页面结构的实现方法
    本篇内容主要讲解“html5页面结构的实现方法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“html5页面结构的实现方法”吧!语义元素介绍HTML5标准增加很多...
    99+
    2022-10-19
  • Golang判断结构体是否存在某方法的两种方式(附代码示例)
    本篇文章带大家学习一下Golang,聊聊Golang怎么判断结构体是不是有某个方法,希望对大家有所帮助。go 判断结构体是否有某个方法go 有时需要判断某个结构体是不是有某个方法,但是可能突然就一脸茫然,go 也可以像 php 那样判断是的...
    99+
    2023-05-14
    Golang
  • Mysql复制表结构、表数据的主要几种方法
    下文主要给大家带来Mysql复制表结构、表数据的主要几种方法,希望这些内容能够带给大家实际用处,这也是我编辑Mysql复制表结构、表数据的主要几种方法这篇文章的主要目的。好了,废话不多说,大家直接看下文吧。...
    99+
    2022-10-18
  • Golang实现解析JSON的三种方法总结
    目录背景示例Json例子解释1)反序列化成map2)反序列化成对象3)复杂json的解析总结背景 这是一篇写给0-1年新人的文章,短平快的教会你如何解析json字符串。 示例Json...
    99+
    2022-11-11
  • Golang端口复用测试的实现方法
    小编给大家分享一下Golang端口复用测试的实现方法,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!先给出结论:同一个进程,使用一个端口,然后连接关闭,大约需要30...
    99+
    2023-06-14
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作