http://play.golang.org/p/j-Y0mQzTdP
package main
import "fmt"
type UselessStruct struct {
a int
b int
}
func main() {
mySlice := make([]*UselessStruct, 5)
for i := 0; i != 5; i++ {
mySlice = append(mySlice, &UselessStruct{})
}
fmt.Println(mySlice)
}
输出:
[<nil> <nil> <nil> <nil> <nil> 0xc010035160 0xc010035170 0xc010035180 0xc010035190 0xc0100351a0]
我想做的是为 5 个 UselessStructs 预分配内存,存储为指针。如果我声明一个结构体值的切片 eq:
mySlice := make([]UselessStruct, 5)
然后这会创建 5 个空结构 - 追加不会替换空结构,而是继续添加到切片,因此此代码的最终结果:
http://play.golang.org/p/zBYqGVO85h
package main
import "fmt"
type UselessStruct struct {
a int
b int
}
func main() {
mySlice := make([]UselessStruct, 5)
for i := 0; i != 5; i++ {
mySlice = append(mySlice, UselessStruct{})
}
fmt.Println(mySlice)
}
是:
[{0 0} {0 0} {0 0} {0 0} {0 0} {0 0} {0 0} {0 0} {0 0} {0 0}]
预分配和填充切片的惯用方法是什么?
对于你的第一个例子,我会这样做:
mySlice := make([]*UselessStruct, 5)
for i := range mySlice {
mySlice[i] = new(UselessStruct)
}
您在两个示例中面临的问题是您要附加到已经具有正确长度的切片。如果您设置
mySlice := make([]*UselessStruct, 5)
,则需要一片长度为 5 的 nil 指针。如果您追加一个指针,它现在的长度为 6。
相反,您想使用
mySlice := make([]*UselessStruct, 0, 5)
。这将创建一个长度为 0 但容量为 5 的切片。每次追加时,它都会为长度加一,但直到超出切片的容量之前,它不会重新分配。
mySlice := make([]*UselessStruct, 0, 5)
for i := 0; i != 5; i++ {
mySlice = append(mySlice, &UselessStruct{})
}
// mySlice is [0xc010035160 0xc010035170 0xc010035180 0xc010035190 0xc0100351a0]
我的两个示例都会按您的预期工作,但我推荐第一个示例纯粹是出于风格原因。
有两种方法可以做到这一点。一种是像您一样预先分配插槽。 但您无需使用
append
,只需索引到现有槽之一即可:
mySlice[i] = &UselessStruct{}
第二种是使用
make
的“重载”版本。您指定零长度,但容量为 5。
package main
type T struct {
A int
B int
}
func main() {
mySlice := make([]*T, 0, 5)
for i := 0; i < 5; i++ {
mySlice = append(mySlice, &T{1, 2})
}
}
mySlice := make([]*T, 0, 5)
初始化长度为零的切片,但它仍然为 5 个条目预先分配足够的空间。
您确定需要指导吗?您的结构体的值为零,因此:
mySlice := make([]UselessStruct, 5) // has memory preallocated for 5 UselessStructs.
由于切片是引用类型,因此您实际上有 5 个指向这 5 个 UselessStructs 的指针。
如果您需要获取对单个结构的引用来传递,那么您可以这样做
myStruct := &mySlice[0]
现在您有了一个指向
UselessStruct
的指针,可以根据需要使用。它的代码比您拥有的少得多,并且利用了 Go 的零值功能。
为了完成:append 与 nil slice 一起工作,因此,您不需要使用 make 创建切片,您只需将元素附加到它即可。
var mySlice []*UselessStruct
for i := 0; i < 5; i++ {
mySlice = append(mySlice, &UselessStruct{})
}
这将与上一个示例相同,无需预先分配,但如果您知道大小,您宁愿使用类似这样的东西:
mySlice := make([]*UselessStruct, 0, 5)
for i := range mySlice {
mySlice[i] = &UselessStruct{}
}
这可能会避免一些重新分配。