如何以一种惯用的方式预分配和填充一些指针?

Dan*_*nte 15 go slice

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)
}
Run Code Online (Sandbox Code Playgroud)

输出: [<nil> <nil> <nil> <nil> <nil> 0xc010035160 0xc010035170 0xc010035180 0xc010035190 0xc0100351a0]

我想做的是为5个UselessStructs预分配内存,存储为指针.如果我声明一片struct值eq:

mySlice := make([]UselessStruct, 5)
Run Code Online (Sandbox Code Playgroud)

然后这会创建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)
}
Run Code Online (Sandbox Code Playgroud)

是: [{0 0} {0 0} {0 0} {0 0} {0 0} {0 0} {0 0} {0 0} {0 0} {0 0}]

预分配和填充切片的惯用方法是什么?

Ste*_*erg 28

对于你的第一个例子,我会这样做:

mySlice := make([]*UselessStruct, 5)
for i := range mySlice {
     mySlice[i] = new(UselessStruct)
}
Run Code Online (Sandbox Code Playgroud)

您在两个示例中遇到的问题是您要附加到已经是正确长度的切片.如果你设置mySlice := make([]*UselessStruct, 5),你要求一片长度为5的零指针.如果你追加一个指针,它现在的长度为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]
Run Code Online (Sandbox Code Playgroud)

我的两个例子都可以按你的预期工作,但我推荐第一个纯粹出于风格的原因.

  • 在 Go 中分配的所有内存都被清零。所以没有白费力气。 (3认同)

jim*_*imt 8

有两种方法可以做到这一点.一种方法是像你一样预先分配插槽.但是append,您只需索引到其中一个现有插槽中,而不是使用它:

mySlice[i] = &UselessStruct{}
Run Code Online (Sandbox Code Playgroud)

第二个是使用'重载'的版本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})
    }
}
Run Code Online (Sandbox Code Playgroud)

mySlice := make([]*T, 0, 5) 初始化切片的长度为零,但它仍然为5个条目预先分配了足够的空间.