2017-03-03 61 views
2

我有一個結構體,我想用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

回答

6

您可以使用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]指定的結構值。

2

您可以使用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