在golang中初始化一个包含结构片断的结构体

在golang中初始化一个包含结构片断的结构体

问题描述:

我有一个结构体,我想用golang中的一片结构体进行初始化,但我试图找出是否有更有效的版本来追加每个新生成的结构到切片:在golang中初始化一个包含结构片断的结构体

package main 

import (
    "fmt" 
    "math/rand" 
) 

type LuckyNumber struct { 
    number int 
} 

type Person struct { 
    lucky_numbers []LuckyNumber 
} 

func main() { 
    count_of_lucky_nums := 10 
    // START OF SECTION I WANT TO OPTIMIZE 
    var tmp []LuckyNumber 
    for i := 0; i < count_of_lucky_nums; i++ { 
     tmp = append(tmp, LuckyNumber{rand.Intn(100)}) 
    } 
    a := Person{tmp} 
    // END OF SECTION I WANT TO OPTIMIZE 
    fmt.Println(a) 
} 
+0

更有效率如何?你只是想跳过tmp变量? https://play.golang.org/p/XKg4VouoUI – JimB

您可以使用make()分配在“全尺寸”的片,然后用for range遍历它,并填补了数字:

tmp := make([]LuckyNumber, 10) 
for i := range tmp { 
    tmp[i].number = rand.Intn(100) 
} 
a := Person{tmp} 
fmt.Println(a) 

试试吧在Go Playground

请注意,在for之内,我没有创建LuckyNumber结构的新“实例”,因为片已经包含了它们;因为切片不是一片指针。因此,在for循环中,我们只需使用由index expressiontmp[i]指定的结构值。

您可以使用make() icza提出了解决方案,你也可以使用这种方式:

tmp := make([]LuckyNumber, 0, countOfLuckyNums) 
for i := 0; i < countOfLuckyNums; i++ { 
    tmp = append(tmp, LuckyNumber{rand.Intn(100)}) 
} 
a := Person{tmp} 
fmt.Println(a) 

这样,您就不必为tmp多次分配内存:你只是做一次,当调用make时。但是,与您要拨打make([]LuckyNumber, countOfLuckyNums)的版本相反,这里tmp只包含初始值,而不是未初始化的归零值。根据你的代码,它可能会有所作为。

+1

我认为你的答案也可以,但为什么其他答案会不止一次地为tmp分配内存? – mgoldwasser

+1

切片'tmp'最初是空的。当您第一次追加到它时,运行时会分配一个小的基础数组并将值放入其中。当您继续追加切片时,一旦达到分配的基础数组的容量,运行时就必须分配一个新的更大的数组,并将所有内容从第一个切换到新切入点。它必须多次执行此操作以适应重复的附加内容(本例中为4个分配:https://play.golang.org/p/_ameESD2-o)。 – Kaedys

+2

哦,而另一个答案也避免了重复分配(Fabien在OP中提到你的版本中有这样的评论)。然而,另一个答案是在'make()'调用中将slice的长度设置为'countOfLuckyNums',而Fabien的版本则分配一个具有该大小的底层数组,但保留片段长度为0.这对于您来说可能很重要出于某种原因,尽早中断追加序列。例如:https://play.golang.org/p/bIs1jmEhrp – Kaedys