2017-04-21 28 views
1

我只是在學習轉到我對將slices傳遞給函數有疑問。如何將切片的副本傳遞給函數?

如果我沒看錯的slices通過引用圍棋過去了,所以如果我做這樣的事情:

package main 

import "fmt" 

func main() { 
    slice := []int{1, 2, 3, 4, 5} 
    fmt.Println(slice) 
    testSlice(slice) 
    fmt.Println(slice) 
} 

func testSlice(slice []int) { 
    slice[0] = 5 
    slice[4] = 1 
} 

testSlice功能實際上將改變原來的slice的值,因爲它通過引用傳遞(默認情況下)。

有一些簡單的方法,我可以直接將slice的副本傳遞給testSlice函數?

當然,我可以做這樣的事情來創建slice的副本:

package main 

import "fmt" 

func main() { 
    slice := []int{1, 2, 3, 4, 5} 
    fmt.Println(slice) 
    testSlice(slice) 
    fmt.Println(slice) 
} 

func testSlice(slice []int) { 
    var newSlice []int 
    for i := 0; i < len(slice); i++ { 
     newSlice = append(newSlice, slice[i]) 
    } 
    newSlice[0] = 5 
    newSlice[4] = 1 
} 

但它需要經過所有的值在原slice複製他們每個人,它似乎並不成爲一個很好的解決方案。

回答

2

有一個內置的功能,copyfunc copy(dst, src []T) int這可能是你在找什麼。它將任何類型的切片複製到另一個切片中。

docs

複製功能支持不同長度的片段之間的複製(它將僅複製到元件的較小的數)。另外,複製可以處理共享相同基礎陣列的源片和目標片,並正確處理重疊片。

所以

list := []string{"hello", "world"} 
newList := make([]string, len(list)) 
n := copy(newList, list) 
// n is the number of values copied 

將複製list到一個新的片newList,其份額值,但不是在存儲器中的參考。 intcopy返回值是複製值的數量。


對於另一種方式,從Kostix的評論,你可以追加切片到一個空的切片。這有點像複製它。它可能不是慣用的,但它允許您將片段傳遞到func作爲副本,類型的。如果你這樣做,我建議大量的意見。

thisFuncTakesSliceCopy(append([]string(nil), list...)) 

到切片追加到另一個切片,記得省略號(...)。

+0

謝謝@Nevermore,這是一個更優雅的方式來複制'切片'。只想確認一下。我無法直接將'slice'拷貝傳遞給一個函數?唯一的方法是手動創建一個新的「切片」並複製原始「切片」中的值?我只是問它,因爲我來自'C++',在那裏我可以通過引用或值傳遞向量。 – KelvinS

+0

@KelvinSalton去絕對沒有「通過參考」的概念。一切都通過價值傳遞。切片是一個底層數組的描述符。如果您想要數組的那部分副本,則必須複製副本。Go的焦點不是「優雅」或「語法糖」,而是「明確的」: – Volker

+0

謝謝@Volker,現在更清晰了。 – KelvinS