2015-02-20 16 views
8

Tôi đang tự hỏi tại sao nó không thể làm như sau trong đi:trộn "bùng nổ" lát và các thông số thường xuyên trong các chức năng variadic

func main() { 
    stuff := []string{"baz", "bla"} 
    foo("bar", stuff...) 
} 

func foo(s ...string) { 
    fmt.Println(s) 
} 

Trong hiểu biết của tôi, lát ... "phát nổ" slice nên nó có thể được sử dụng cho các cuộc gọi hàm đa đối số. Vì vậy, ví dụ trên thực sự nên mở rộng đến foo("bar", "baz", "bla").

foo(stuff...) hoạt động như mong đợi, không có bất ngờ ở đây, nhưng trong ví dụ trên, trình biên dịch than phiền về quá nhiều đối số.

Đây có phải là giới hạn mong muốn không? Tôi đến từ một nền ruby ​​nơi một foo("bar", *stuff) là hoàn toàn tốt đẹp (và, ít nhất là trong cuốn sách của tôi, điều tương tự), đó là lý do tại sao điều này làm tôi ngạc nhiên.

Trả lời

7

Giá trị cho một cuộc tranh luận variadic thể được chỉ định hoặc bằng cách liệt kê các yếu tố, hoặc sử dụng một lát hiện có, xác định bởi tên của nó tiếp theo ....

Bạn muốn kết hợp 2 cách có thể không được phép theo Đặc tả ngôn ngữ đi (Passing arguments to ... parameters).

Nếu hình thức đầu tiên được sử dụng (liệt kê các yếu tố):

The value passed [as the variadic parameter] is a new slice of type []T with a new underlying array whose successive elements are the actual arguments.

Nếu sau này được sử dụng (đi qua một lát hiện tiếp theo ...) không lát mới được tạo, là bạn vượt qua là được sử dụng như là. Và lát cắt chỉ có thể được sử dụng để xác định giá trị của một - số cuối cùng - tham số variadic. Cố gắng vượt qua cả một yếu tố duy nhất một lát sẽ không khớp với chữ ký (danh sách tham số trong trường hợp này) của chức năng của bạn và bạn sẽ nhận được một lỗi:

too many arguments in call to foo 

Không có thực tế "bùng nổ" tham gia vào Go, thuật ngữ này chỉ được sử dụng trong các ngôn ngữ khác để giúp hình dung rằng mảng hoặc lát đã qua sẽ không phải là một phần tử của thông số variadic nhưng sẽ là giá trị của tham số variadic chính nó.

Trộn 2 sẽ yêu cầu cấp phát một lát mới vì rõ ràng không thể sử dụng slice hiện có.

5

Các đặc điểm kỹ thuật về vấn đề này là ở "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 .

Trong trường hợp của bạn, nơi thứ ... hoạt động:

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.

Nhưng "bar", stuff... không phù hợp với cả hai trường hợp nêu trên .

T, []T không khớp với f([]T).

Các vấn đề liên quan