Golang里空结构体struct{}的介绍和使用

s t r u c t struct struct G o l a n g Golang Golang里的关键字,用于定义结构类型
比如

type Student struct{id intname string
}

struct{}是有 0 0 0个元素的结构体.
struct{}{}表示类型struct{}的值为空{}

1.性质

1.1不占用内存

大小为 0 0 0,不需要内存来存储struct{}类型的值。

func Test_Size(t *testing.T) {var x intvar y stringvar z struct{}t.Log(unsafe.Sizeof(x), unsafe.Sizeof(y), unsafe.Sizeof(z)) //8 16 0
}

在这里插入图片描述

1.2 地址相同

定义两个struct{}类型的变量,打印并比较其地址,发现是相同的

func Test_Address(t *testing.T) {var x struct{}var y struct{}t.Logf("%p %p %v %v", &x, &y, &x == &y, x == y) // 0x1290460 0x1290460 true true
}

在这里插入图片描述

2.用途

2.1实现set

golang里没有实现set,如果在使用map的时候只关心key,不关心value的话,可以借助struct{}来实现set。比如key为string类型,那么set的实现map[string]struct{}。
因为struct{}不占用空间,所以在查找和判断的过程中速度会快,而且占用的内存也会小
简单实现:

func Test_set(t *testing.T) {set := make(map[string]struct{})set["a"] = struct{}{}if _, ok := set["a"]; ok {t.Log("exists") //exists}
}

在这里插入图片描述

使用interface{}实现

type Set map[interface{}]struct{}func (s Set) Add(item interface{}) {s[item] = struct{}{}
}func (s Set) Remove(item interface{}) {delete(s, item)
}func (s Set) Contains(item interface{}) bool {_, exists := s[item]return exists
}func Test_any_set(t *testing.T) {set := make(Set)set.Add("apple")set.Add("banana")set.Add("orange")fmt.Println("Set:", set)fmt.Println("Contains apple:", set.Contains("apple"))fmt.Println("Contains grape:", set.Contains("grape"))set.Remove("banana")fmt.Println("Set:", set)
}

在这里插入图片描述
使用泛型实现:

type Set[T comparable] map[T]struct{}func (s Set[T]) Add(v T) {s[v] = struct{}{}
}func (s Set[T]) Remove(v T) {delete(s, v)
}func (s Set[T]) Contains(v T) bool {_, ok := s[v]return ok
}func (s Set[T]) Len() int {return len(s)
}func (s Set[T]) Values() []T {values := make([]T, 0, s.Len())for v := range s {values = append(values, v)}return values
}func Test_any_set(t *testing.T) {s := Set[string]{}s.Add("apple")s.Add("banana")s.Add("orange")fmt.Println("Set:", s.Values())fmt.Println("Contains apple:", s.Contains("apple"))fmt.Println("Contains grape:", s.Contains("grape"))s.Remove("banana")fmt.Println("Set:", s.Values())
}

在这里插入图片描述

2.2. 用于无数据的channel

有的时候 c h a n n e l channel channel不需要发送数据,只需要一个触发信号,就可以使用struct{}来减少信号传递过程中的内存开销
a. 等待协程完成
w o r k e r worker worker函数是一个协程,它会模拟一些工作并在完成后发送空结构体值到 d o n e done done通道。
T e s t _ w a i t Test\_wait Test_wait函数中,我们通过从 d o n e done done通道接收空结构体值来等待工作完成。

func worker(done chan struct{}) {fmt.Println("Worker: Performing some work...")time.Sleep(2 * time.Second)fmt.Println("Worker: Work completed!")done <- struct{}{} // 发送空结构体值表示工作完成
}
func Test_wait(t *testing.T) {done := make(chan struct{})go worker(done)<-done // 接收空结构体值,等待工作完成t.Log("Main: Done!")
}

在这里插入图片描述

b.触发事件
w a i t F o r E v e n t waitForEvent waitForEvent函数会等待接收到空结构体值,表示事件发生。
t r i g g e r E v e n t triggerEvent triggerEvent函数会在一段时间后发送空结构体值到event通道,表示事件发生。
通过使用空结构体值作为通道元素,我们可以简单地实现事件的触发和等待。

func waitForEvent(event chan struct{}) {fmt.Println("Waiting for event...")<-event // 等待接收到空结构体值,表示事件发生fmt.Println("Event received!")
}func triggerEvent(event chan struct{}) {time.Sleep(2 * time.Second)fmt.Println("Triggering event...")event <- struct{}{} // 发送空结构体值,表示事件发生
}
func Test_event(t *testing.T) {event := make(chan struct{})go waitForEvent(event)go triggerEvent(event)time.Sleep(3 * time.Second)
}

在这里插入图片描述

2.3 方法接收器

实现一个接口,只需要实现一些方法,不用声明一些额外的数据,可以用struct{}来实现,也可以换成其他任意的变量,比如 i n t int int b o o l bool bool

type Animal interface {Shouting()
}
type Dog struct{}func (dog *Dog) Shouting() {fmt.Println("wang wang wang")
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/323927.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

python-查漏补缺笔记-更新中

包导入时__init__.py中命令的执行顺序和sys.modules变化 ref: https://edu.csdn.net/skill/practice/python-3-6/164 在有父包和子包的情况下&#xff0c;父包中的“ __ init__.py”语句会在子包的“ __ init__.py”语句之前执行&#xff0c;然后按下列顺序执行导入子包和模块…

Mac 安装Nginx教程

Nginx官网 Nginx官网英文 1.在总段输入brew search nginx 命令检查nginx是否安装了 2. 安装命令&#xff1a;brew install nginx 3. 查看Nginx信息命令brew info nginx 4. 启动 nginx方式&#xff1a;在终端里输入 nginx 5.查看 nginx 是否启动成功 在浏览器中访问http://l…

如何打造家居产业数字化转型范式?林氏家居以数智供应链作答

近年来&#xff0c;我国房地产行业逐步进入深度调整期。作为下游产业&#xff0c;家居家装行业的发展也来到了新阶段。业内人士指出&#xff0c;新房市场成交规模收缩&#xff0c;家居家装企业们开始整合资源&#xff0c;向存量房市场、产品科技化以及数字化转型。 国家层面出…

实验4.4 动态路由OSPF协议的配置

实验4.4 动态路由OSPF协议的配置 一、任务描述二、任务分析三、具体要求四、实验拓扑五、任务实施1.配置交换机和路由器的接口的IP地址等参数。2.配置动态路由OSPF协议&#xff0c;实现全网互通。 六、任务验收七、任务小结八、知识链接1&#xff0e;OSPF协议概念2&#xff0e;…

qiankun 公共依赖

1、提取公共依赖的目的 减少相同资源的重复加载资源版本不同步打包文件庞大2、如何提取公共依赖 基本思路&#xff1a;1、相同依赖 采用 CDN 的方式加载&#xff0c;并把 所有依赖的 CDN 链接 统一放到一个文件中进行管理 2、把存放 CDN 链接的文件&#xff0c;引入到 vue.conf…

基于OpenCV的图像平移

基本概念 图像的平移操作是将图像的所有像素坐标进行水平或者垂直方向的移动&#xff0c;也就是所有像素点按照给定的偏移量在水平方向上沿X轴&#xff0c;垂直方向上沿y轴移动。 设原始图像像素点为&#xff08;x0,y0&#xff09;&#xff0c;平移后的图像的像素点为(x,y),x…

接口开发—hrun语法和用例规范

学习目标&#xff1a; 1、常见的抓包方法 2、如何提取和使用token 3、用例规范 4、辅助函数 具体内容&#xff1a; 1、常见的抓包方法 做接口测试前&#xff0c;肯定需要使用抓包工具去请求接口&#xff0c;然后才开始正常写接口用例。 常用的2种抓包方法有&#xff1a…

FreeRTOS——内存管理知识总结及实战

1 freeRTOS动态创建与静态创建 动态创建&#xff1a;从FreeRTOS 管理的内存堆中申请创建对象所需的内存&#xff0c;在对象删除后&#xff0c; 这块内存释放回FreeRTOS管理的内存堆中 静态创建&#xff1a;需用户提供各种内存空间&#xff0c;并且使用静态方式占用的内存空间一…

分配器allocators

STL六大组件之一分配器allocators 分配器&#xff1a;负责空间的配置与管理&#xff08;写在容器类型的后面&#xff0c;如右图&#xff0c;作用是帮容器分配内存&#xff0c;一般都 会省略不写&#xff0c;源代码有默认的&#xff09; #include <vector>vector<…

linux下安装Nginx及其常用命令

安装Nginx 接下来在Linux服务器进行操作就可以了 安装插件 yum -y install gcc pcre-devel zlib-devel openssl openssl-devel直接使用wget进行安装(如果没有wget需要先安装wget) yum install wgetwget https://nginx.org/download/nginx-1.24.0.tar.gz解压 tar -zxvf nginx..…

python的课后练习总结4(while循环)

for循环用于针对序列中的每个元素的一个代码块。 while循环是不断的运行&#xff0c;直到指定的条件不满足为止。 while 条件&#xff1a; 条件成立重复执行的代码1 条件成立重复执行的代码2 …….. i 1while i < 5:print(i)i i 11、使用wh…

pypdf 将 PDF两个页面拼接成一个页面进一步详解

pypdf 原库名Pypdf2(已弃用&#xff0c;文档 PyPDF2 RectangleObject类_w3cschool) pypdf 官方文档 The Transformation Class — pypdf 3.17.4 documentation pypdf 将两个PDF页面在x轴&#xff0c;y轴进行平移调整位置之后&#xff0c;直接用merge_page拼接在一起&#xff…