go语言-空结构体/ chan struct{}
文章目录
- 空结构体 struct{}
- chan struct{}
- 常用用法
- 带缓冲的chan struct{}数据读写
空结构体 struct{}
空结构体的宽度是0,占用了0字节的内存空间。
var s struct{}
fmt.Println(unsafe.Sizeof(s)) // prints 0
由于空结构体占用0字节,那么空结构体也不需要填充字节。所以空结构体组成的组合数据类型也不会占用内存空间。
type S struct {A struct{}B struct{}}var s Sfmt.Println(unsafe.Sizeof(s)) // prints 0
chan struct{}
通过消息来共享数据是golang的一种设计哲学,channel则是这种哲理的体现。
golang中的空结构体 channel := make(chan struct{})
特点
- 省内存,尤其在事件通信的时候。
- struct零值就是本身,读取close的channel返回零值
常用用法
通常struct{}类型channel的用法是使用同步,一般不需要往channel里面写数据,只有读等待,而读等待会在channel被关闭的时候返回。
type Miner struct {api api.FullNodeepp gen.WinningPoStProverlk sync.Mutexaddress address.Addressstop chan struct{}stopping chan struct{}waitFunc waitFunclastWork *MiningBaseminedBlockHeights *lru.ARCCache
}
stop 它是一个管道chan,内部的数据类型是struct{}。
单独拿struct{}来说,我们熟悉type Name struct{a int, b bool}这样去定义一个结构体的类型,其实struct{…}就是定义结构体,和map[string]int这种定义是一样的,type只是给它取了一个别名。 总结: 实际上struct{}就是一种普通数据类型,只是没有具体的值而已。
注意,channel对象一定要make出来才能使用。, 如下,make后赋值给m
func (m *Miner) Start(ctx context.Context) error {m.lk.Lock()defer m.lk.Unlock()if m.stop != nil {return fmt.Errorf("miner already started")}m.stop = make(chan struct{})go m.mine(context.TODO())return nil
}func (m *Miner) Stop(ctx context.Context) error {m.lk.Lock()defer m.lk.Unlock()m.stopping = make(chan struct{})stopping := m.stoppingclose(m.stop)select {case <-stopping:return nilcase <-ctx.Done():return ctx.Err()}
}
使用场景
首先事件通知,可以通过写入 通知其他协程,但是只能通知一个。
channel := make(chan struct{})
go func() {// ... do somethingchannel <- struct{}{}
}()
fmt.Println(<-channel)
和close进行配合,通知所有相关协程。
在读入被close的channel返回零值,正常的协程是读取不到这个close的。
close之后,所有协程都可以读到。
比较经典的例子就是用于stopChan作为停止channel通知所有协程。
在下面的例子中 我们可以通过s.Stop()通知所有的serverHandler协程停止工作,并且等待他们正常退出。
type Server struct {serverStopChan chan struct{}stopWg sync.WaitGroup
}
func (s *Server) Stop() {if s.serverStopChan == nil {panic("gorpc.Server: server must be started before stopping it")}close(s.serverStopChan)s.stopWg.Wait()s.serverStopChan = nil
}
func serverHandler(s *Server){for {select {case <-s.serverStopChan:returndefault:// .. do something}}
}
带缓冲的chan struct{}数据读写
另外也可以定义带缓冲的channel
package mainimport ("time""log"
)var ch chan struct{} = make(chan struct{}, 2)func foo() {ch <- struct{}{}log.Println("foo() 000");ch <- struct{}{}log.Println("foo() 111");time.Sleep(5 * time.Second)log.Println("foo() 222");close(ch)log.Println("foo() 333");
}func main() {var b struct{}log.Println("main() 111");go foo()log.Println("main() 222");a := <-chlog.Println("main() 333", a);b = <-chlog.Println("main() 444", b);c := <-chlog.Println("main() 555", c);
}
<-ch用来从channel ch中接收数据,这个表达式会一直被block,直到有数据可以接收。
从一个nil channel中接收数据会一直被block。(往nil channel中发送数据会一致被阻塞着。)
从一个被close的channel中接收数据不会被阻塞,而是立即返回,接收完已发送的数据后会返回元素类型的零值(zero value)。
如前所述,你可以使用一个额外的返回参数来检查channel是否关闭。
x, ok := <-ch
x, ok = <-ch
var x, ok = <-ch
如果OK 是false,表明接收的x是产生的零值,这个channel被关闭了或者为空。
go语言-空结构体/ chan struct{}相关推荐
- Go 空结构体的 3 种使用场景
转子地址:https://mp.weixin.qq.com/s/zWzyl6x9sZdXZCaAuva2lA 在 Go 语言中,有一个比较特殊的类型,经常会有刚接触 Go 的小伙伴问到,又或是不理解. ...
- go struct{} 空结构体的特点和作用
空结构体的特点和作用 参考代码 package mainimport ("fmt""unsafe" )func main() {empStruct() } // ...
- Go语言结构体(struct)
Go 语言通过用自定义的方式形成新的类型,结构体是类型中带有成员的复合类型.Go 语言使用结构体和结构体成员来描述真实世界的实体和实体对应的各种属性. Go 语言中的类型可以被实例化,使用new或&a ...
- C 语言实例 - 使用结构体(struct)
C 语言实例 - 使用结构体(struct)C 语言实例 C 语言实例 使用结构体(struct)存储学生信息. 实例 #include <stdio.h> struct student ...
- C语言结构体(Struct)
C语言结构体(Struct) 在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据.结构体的定义形式为: struct 结构体名{ 结构体所包含的变量或数组 }; 结构体是一种集合,它里 ...
- [ C语言 ]指针---结构体(struct)---分支语句(1)---初识C语言末尾
文章目录 前言 一,指针 二,结构体(struct) 三,分支语句(选择结构) 总结 前言 本篇文章主要记录指针末尾,结构体,和分支语句(选择结构) --------------------- ...
- 【C语言】结构体定义 typedef struct 用法详解和用法小结
结构体定义 typedef struct 用法详解和用法小结 文章目录 结构体定义 typedef struct 用法详解和用法小结 0. 前言 1. 首先:在C中定义一个结构体类型要用typedef ...
- C语言结构体(struct)最全的讲解(万字干货)
结构体的定义 结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,也叫结构. 结构体和其他类型基础数据类型一样,例如int类型,char类型只不过结构体可以做成你想要的数据类型 ...
- C语言中结构体struct的用法
点击蓝字 关注我们 定义结构体变量 下面举一个例子来说明怎样定义结构体变量. struct string { char name[8]; int age; char sex[2]; char depa ...
最新文章
- PyQt5 技术篇-透明窗口设置方法,窗口透明度的设置
- oracle数据库用户创建_权限分配_以及导入_导出数据,oracle数据库用户创建、权限分配,以及导入,导出数据...
- php 解析返回的xml,php解析cas返回的xml解决思路
- ORA-28002:密码过期时的处理…………
- python3 input函数
- OpenUDID 和 IDFA 比较
- laravel 社会化(联合)登录扩展包(QQ、微信、微博等)
- 广州宽带市场割喉战:电信地狱价小企业陷两难
- 一旦停下来,就很难再继续下去了--《一个人的朝圣》
- AE-摄影机和跟踪器
- HTMLCSS 【三】-- TABLES, DIVS, AND SPANS
- 天融信上网行为管理短信对接教程
- Tableau 八、数据分层、数据分组、数据集
- 8、RH850 F1 IIC通讯功能和配置
- 【多线程编程学习笔记6】终止线程执行,千万别踩这个坑!
- 载誉而归丨盐城卓晨中心在第十届“北大青鸟杯”IT精英挑战赛中斩获多项殊荣!
- 信息安全工程师参考试题
- 供给与需求的市场力量 - 异想天开
- 基于JAVA EE的驾校驾照考试系统
- 华为思科设备NTP配置
热门文章
- 在线创建LaTeX表格的方法
- 高效管理时间的黄金法则
- 游戏辅助制作核心--植物大战僵尸逆向之植物攻击加速(六)
- python列表中单个元素的访问方式_从boost::python::object列表中获取单个元素,用于python routin...
- c语言学生请假系统项目总结,学生管理系统项目总结.doc
- 动态网页和静态网页的差异
- MATLAB绘制平面填充图入门详解
- 如何推动智慧交通普惠发展 | 工信部印发民用无人机《指导意见》
- 网站SEO优化一一百度搜索资源平台
- 母猪公司和沙丁鱼罐头