Golang 中的 struct{}
空接口類型
基本類型大小
- struct{}
- 大小
- 地址
- 被包含
- 獨立
- 作用
- map
- chain struct{}
先看一個例子
type NilStruct struct{}
type Man struct {
None NilStruct
Name string
}
func main() {
ns1 := NilStruct{}
man := Man{}
ns2 := NilStruct{}
fmt.Printf("%p\n%p\n%p\n%p\n", &ns1, &ns2, &(man.None), &man)
}
輸出是
0x564178
0x564178
0xc000014250
0xc000014250
我們發現 ns1 和 ns2 擁有相同的地址,man.None 和 man 擁有相同的地址。前者是因爲所有空接口都有用相同地址,這個地址被定義在 runtime/malloc.go 當中。
// base address for all 0-byte allocations
var zerobase uintptr
即所有 0-byte 的變量地址都爲 zerobase。而空接口正是大小爲零的數據結構。那麼爲何後面 man.None 的地址不一樣呢?那是因爲這時的 man.None 的地址並不是空接口的地址,而是結構體的起始地址(所以其與 man 的地址相同),具體的我們以後再說。
有什麼作用
map + struct{} = set
Golang 並沒有提供 set 這種數據結構,即一種表示所有元素都唯一的集和的數據結構。但是你可以通過 map + struct 的方式實現。
type set map[string]struct{}
你可能會說 type
Set
map``[``string``]``bool
這樣也可以啊。是的,這樣也可以,但是 struct{} 有一個優勢,那就是 struct{} 的大小爲0,且其值永遠爲 struct{},而 bool 的數據大小爲 1 Byte,且數據值可以有 true 和 false 兩種(可能存在誤導,或者存了值,但卻沒有意義,這是一種浪費)。
chan + struct = TODO
如果你希望通過一個通道來通知另一個攜程做些什麼,但是又並不需要傳遞任何實質性的數據。那麼你就可以使用 chan + struct{} 的方式來實現一個有只能用於發送通知,卻沒有傳遞數據的通道。
type ready chan struct{}
總結
- struct{} 佔用內存爲 0。
- 所有獨立的 struct{} 擁有相同的地址。
- 被結構體包含的 struct{} 地址跟隨結構體。
- struct{} 可與 map 結合實現 set 數據結構。
- struct{} 可與 chan 結合實現無數據交互的,僅用於通知的通道。