golang函數可變參數傳遞性能問題

幾天前糾結了一個蛋疼的問題,在go裏面函數式支持可變參數的,譬如...T,go會創建一個slice,用來存放傳入的可變參數,那麼,如果創建一個slice,例如a,然後以a...這種方式傳入,go會不會還會新建一個slice,將a的數據全部拷貝一份過去?

如果a很大,那麼將會造成很嚴重的性能問題,不過後來想想,可能是自己多慮了,於是查看go的文檔,發現如下東西:

Passing arguments to ... parameters

If f is variadic with a final parameter p of type ...T, then within f the type of p is equivalent to type []T. If f is invoked with no actual arguments for p, the value passed to p is nil. Otherwise, the value passed is a new slice of type []T with a new underlying array whose successive elements are the actual arguments, which all must be assignable to T. The length and capacity of the slice is therefore the number of arguments bound to p and may differ for each call site.

Given the function and calls

func Greeting(prefix string, who ...string)
Greeting("nobody")
Greeting("hello:", "Joe", "Anna", "Eileen")

within Greeting, who will have the value nil in the first call, and []string{"Joe", "Anna", "Eileen"} in the second.

If the final argument is assignable to a slice type []T, it may be passed unchanged as the value for a ...T parameter if the argument is followed by .... In this case no new slice is created.

Given the slice s and call

s := []string{"James", "Jasmine"}
Greeting("goodbye:", s...)

within Greeting, who will have the same value as s with the same underlying array.

也就是說,如果我們傳入的是slice...這種形式的參數,go不會創建新的slice。寫了一個簡單的例子驗證:

package main

import "fmt"

func t(args ...int) {
    fmt.Printf("%p\n", args)
}

func main() {
    a := []int{1,2,3}
    b := a[1:]

    t(a...)
    t(b...)

    fmt.Printf("%p\n", a)
    fmt.Printf("%p\n", b)
}

//output
0x1052e120
0x1052e124
0x1052e120
0x1052e124

可以看到,可變參數args的地址跟實際外部slice的地址一樣,用的同一個slice。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章