什么是struct{}和struct{}{}
struct {}是一种普通数据类型,一个无元素的结构体类型,通常在没有信息存储时使用。 优点是大小为0,不需要内存来存储struct {}类型的值。
struct {} {}:实例化一个struct{}类型的数据,大小为0。
验证struct{}大小为0
var s struct{}
fmt.Println(unsafe.Sizeof(s)) //输出0
struct{}组成的struct大小也为0
type S struct {
A struct{}
B struct{}
}
var s S
fmt.Println(unsafe.Sizeof(s)) //输出0
unsafe.Sizeof()介绍
unsafe的软件包可能不可移植,并且不受Go 1兼容性指南的保护。虽然有几个函数在不安全的unsafe包,但是这几个函数调用并不是真的不安全,特别在需要优化内存空间时它们返回的结果对于理解原生的内存布局很有帮助。
unsafe.Sizeof()总是在编译期就进行求值,而不是在运行时,这意味着返回值可以赋值给常量。我们这里可以使用unsafe.Sizeof()获取struct大小。
channel中使用struct{}
一般通过 channel := make(chan struct{})创建一个空channel,使用struct{}的在事件通信时可以节省内存。
使用struct{}作为无缓冲channel标志
这里创建了一个channel,并创建了一个协程。协程中等待10秒才会写入消息,这个消息的类型是struct{},内容为{},大小为0。
type connection struct {
stop chan struct{}
}
var con connection
con.stop = make(chan struct{})
go func() {
fmt.Println("等待10秒")
time.Sleep(time.Second * 10)
con.stop <- struct{}{} //表示传递结束信息
}()
<-con.stop
fmt.Println("此消息的大小为:", unsafe.Sizeof(<-con.stop)) //输出0
fmt.Println("协程结束了")
使用struct{}作为有缓冲channel标志
有缓冲时可以定义任意个标志(操作系统联系死锁可以用这个玩)。
type connection struct {
stop chan struct{}
}
var con connection
con.stop = make(chan struct{}, 2) //缓冲容量为2
go func() {
fmt.Println("第一个协程等待4秒")
time.Sleep(time.Second * 4)
con.stop <- struct{}{} //表示传递结束信息
}()
go func() {
fmt.Println("第二个协程等待3秒")
time.Sleep(time.Second * 3)
con.stop <- struct{}{} //表示传递结束信息
}()
<-con.stop
fmt.Println("第一个协程结束了")
<-con.stop
fmt.Println("第二个协程结束了")
fmt.Println("协程结束了")