func main() {
var s struct{}
fmt.Println(unsafe.Sizeof(s))
}
输出结果:
0
这是Go 编译器在内存分配时做的优化项
// base address for all 0-byte allocations
var zerobase uintptr
// Allocate an object of size bytes.
// Small objects are allocated from the per-P cache's free lists.
// Large objects (> 32 kB) are allocated straight from the heap.
func mallocgc(size uintptr, typ *_type, needzero bool) unsafe.Pointer {
...
if size == 0 {
return unsafe.Pointer(&zerobase)
}
}
当发现 size 为 0 时,会直接返回变量 zerobase 的引用,该变量是所有 0 字节的基准地址,不占据任何宽度。
type T struct{}
func (s *T) Call() {
}
集合类型的使用,只需要用到 key(键),不需要 value(值)
type Set map[string]struct{}
func (s Set) Append(k string) {
s[k] = struct{}{}
}
func (s Set) Remove(k string) {
delete(s, k)
}
func (s Set) Exist(k string) bool {
_, ok := s[k]
return ok
}
func main() {
set := Set{}
set.Append("1")
set.Append("2")
set.Append("3")
set.Remove("1")
fmt.Println(set.Exist("1"))
}
空结构体作为占位符,不会额外增加不必要的内存开销
在 Go channel 的使用场景中,常常会遇到通知型 channel,其不需要发送任何数据,只是用于协调 Goroutine 的运行,用于流转各类状态或是控制并发情
func main() {
ch := make(chan struct{})
go func() {
time.Sleep(1 * time.Second)
close(ch)
}()
fmt.Println("1")
<-ch
fmt.Println("2")
}
由于该 channel 使用的是空结构体,因此也不会带来额外的内存开销