Golang的…语法真的只是可变参数吗?

huangapple go评论85阅读模式
英文:

Is Golang's ... syntax really just varargs?

问题

好的,以下是翻译的内容:

嗯,我有一个简单的例子,虽然可能看起来毫无意义,但这些例子与我的认知相去甚远。

有人可以告诉我发生了什么吗?

我使用...语法将[]int中的元素传递给参数args,但当我改变形式参数args时,[]int的实际参数也被改变了。

我修改了args的顺序,但[]int的顺序也受到了影响:

package main

import (
	"fmt"
)

func bubbleSort(args ...int) {
	for i := 0; i < len(args); i++ {
		for j := 0; j < len(args)-1; j++ {
			if args[j] > args[j+1] {
				args[j], args[j+1] = args[j+1], args[j]
			}
		}
	}
}

func main() {
	isle := []int{3, 6, 1, 2, 5}
	bubbleSort(isle...)

	fmt.Printf("%v\n", isle)
}

// [1 2 3 5 6]

如果我传入单个参数会怎样?显然[]int不会受到args的影响:

package main

import (
	"fmt"
)

func bubbleSort(args ...int) {
	for i := 0; i < len(args); i++ {
		for j := 0; j < len(args)-1; j++ {
			if args[j] > args[j+1] {
				args[j], args[j+1] = args[j+1], args[j]
			}
		}
	}
}

func main() {
	isle := []int{3, 6, 1, 2, 5}
	bubbleSort(isle[0], isle[1], isle[2], isle[3], isle[4])

	fmt.Printf("%v\n", isle)
}

// [3 6 1 2 5]
英文:

Well, I have a simple example, although it may seem pointless, but these examples have deviated greatly from my cognition.

Can anyone tell me what happened.

I pass the elements in []int to the parameter args with the ... syntax, but when I change the formal parameter args, the []int actual parameter is changed.

I modified the ordering of args , but the ordering of []int is also affected:

package main

import (
	&quot;fmt&quot;
)

func bubbleSort(args ...int) {
	for i := 0; i &lt; len(args); i++ {
		for j := 0; j &lt; len(args)-1; j++ {
			if args[j] &gt; args[j+1] {
				args[j], args[j+1] = args[j+1], args[j]
			}
		}
	}
}

func main() {
	isle := []int{3, 6, 1, 2, 5}
	bubbleSort(isle...)

	fmt.Printf(&quot;%v\n&quot;, isle)
}

// [1 2 3 5 6]

What if I pass in a single parameter? Apparently []int is not affected by args:

package main

import (
	&quot;fmt&quot;
)

func bubbleSort(args ...int) {
	for i := 0; i &lt; len(args); i++ {
		for j := 0; j &lt; len(args)-1; j++ {
			if args[j] &gt; args[j+1] {
				args[j], args[j+1] = args[j+1], args[j]
			}
		}
	}
}

func main() {
	isle := []int{3, 6, 1, 2, 5}
	bubbleSort(isle[0], isle[1], isle[2], isle[3], isle[4])

	fmt.Printf(&quot;%v\n&quot;, isle)
}

// [3 6 1 2 5]

答案1

得分: 1

Golang不像Rust那样关注"变量安全性"。因此,你永远不应该认为传递给函数的切片不会被破坏。

如果你想使用可变参数函数但又要传递切片,请进行复制:

func myUnsafeFunc(args ...int) { 
   // 它会改变args
}
func wantToSaveSliceFunc() {
   myLovingSlice := []int{1,2,3}
   myUnsafeFunc(append([]int(nil), slice...)...)
}

https://freshman.tech/snippets/go/copy-slices/

如果你记住spread operator ...只是一种语法糖,就不会感到困惑。

除非有充分的理由(例如在fmt.Printf(...)中),不要在自己的API中使用它,而是优先使用显式的x []type表示法而不是x ...type

func myUnsafeFunc(args []int) { 
   // 它会改变args
}
func wantToSaveSliceFunc() {
   myLovingSlice := []int{1,2,3}
   myUnsafeFunc(append([]int(nil), slice...))
}

虽然仍然需要复制切片,但从语义上来说更清晰。

英文:

Golang is not about "variable safety" as Rust. So you shoud never think that slice sent to function will not be corrupted.

If you want to use variadic functions but send slices, copy it:

func myUnsafeFunc(args ...int) { 
   // it will change args
}
func wantToSaveSliceFunc() {
   myLovingSlice := []int{1,2,3}
   myUnsafeFunc(append([]int(nil), slice...)...)
}

https://freshman.tech/snippets/go/copy-slices/

It's not confusing if you remember that spread operator ... is just a shugar .

Do not use it in your own API without serious reasone (as in fmt.Printf(...) for example) prefer use of explicit x []type notation over x ...type:

func myUnsafeFunc(args []int) { 
   // it will change args
}
func wantToSaveSliceFunc() {
   myLovingSlice := []int{1,2,3}
   myUnsafeFunc(append([]int(nil), slice...))
}

it still requires copying of slice, but it's much clear by semantics

huangapple
  • 本文由 发表于 2022年12月29日 00:17:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/74942547.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定