Go Slice 里面放 Struct,應(yīng)該使用指針嗎?
很多人寫go 也寫了好多年了,但還是對(duì)go 的內(nèi)存結(jié)構(gòu)一無所知,除了內(nèi)存對(duì)齊以外,比如slice 里面到底應(yīng)該放結(jié)構(gòu)體([]MyStruct)還是結(jié)構(gòu)體指針([]*MyStruct),還是一頭霧水。
Go slice 里面放struct 應(yīng)該使用指針嗎?
我們先通過一個(gè)性能測(cè)試,看一下這兩種情況下的性能對(duì)比:
我們先定義一個(gè)結(jié)構(gòu)體:
- type MyStruct struct {
- A int
- B int
- }
然后通過go自帶的benchmark測(cè)試一下,首先是使用指針的場(chǎng)景:
- func BenchmarkSlicePointers(b *testing.B) {
- b.ReportAllocs()
- for i := 0; i < b.N; i++ {
- slice := make([]*MyStruct, 0, 100)
- for j := 0; j < 100; j++ {
- slice = append(slice, &MyStruct{A: j, B: j + 1})
- }
- }
- }
然后是直接放結(jié)構(gòu)體的場(chǎng)景:
- func BenchmarkSliceNoPointers(b *testing.B) {
- b.ReportAllocs()
- for i := 0; i < b.N; i++ {
- slice := make([]MyStruct, 0, 100)
- for j := 0; j < 100; j++ {
- slice = append(slice, MyStruct{A: j, B: j + 1})
- }
- }
- }
跑一下:
- name time/op
- SlicePointers-8 2.50µs ± 2%
- SliceNoPointers-8 117ns ± 1%
- name alloc/op
- SlicePointers-8 1.60kB ± 0%
- SliceNoPointers-8 0.00B
- name allocs/op
- SlicePointers-8 100 ± 0%
- SliceNoPointers-8 0.00
可以看到使用指針的時(shí)候的性能要明顯低于直接使用結(jié)構(gòu)體,原因也很明顯,因?yàn)槭褂弥羔樀臅r(shí)候,切面里面放的是指針,指針在單獨(dú)指向一個(gè)內(nèi)存區(qū)域,而直接使用結(jié)構(gòu)體則可以節(jié)省這部分的開銷。
所以,只有我們需要修改原來數(shù)據(jù),必須指針傳遞的時(shí)候,我們才將指針放到slice里面,這點(diǎn)希望大家注意。