我还是编程新手。原谅我缺乏计算机科学知识。不确定这个问题是不是专门针对Golang或一般的计算机科学...
我一直认为,函数不会更改其自身作用域之外的变量/数据,除非您在其他作用域中使用return语句,或者它们在作用域的层次结构中较高。有人可能会争辩说,此示例中的函数f1
和f2
是从较低范围调用的。但是,这仍然不能解释为什么我对于变量num
和nums
会得到不同的结果。
package main
import "fmt"
func f1(a int) {
a = 50 // this will not work, as it shouldn't
}
func f2(a ...int) {
a[0] = 50 // this will work without return statement
a[1] = 50 // this will work without return statement
}
func main() {
num := 2
nums := []int{2, 2}
f1(num)
f2(nums...)
fmt.Printf("function f1 doesn't affect the variable num and stays: %v\n", num)
fmt.Printf("function f2 affects the variable nums and results in: %v", nums)
问题:f2
不需要return语句来修改num之类的num会在
f1
中吗? 那不应该强迫函数返回副本吗?
看到其他语言)。
最佳答案
这是正确的行为,因为a ...int
等于 slice ,例如:a []int
func f2(a []int) {
a[0] = 50
a[1] = 50
}
func main() {
b := []int{2, 2}
f2(b)
fmt.Println(b) // [50 50]
}
slice 是原始数据(这里为“b”)的视图。“为什么f2不需要return语句来像num一样修改f1中的num?”
在
f2
中,您使用的是 slice ,该 slice 具有指向原始数组的指针,因此f2
可以更改外部数组。“据说Golang函数传递值(不是引用),这不应该强制返回副本吗?(如果问题与之相关...)”
在
f2
中, slice 本身通过值传递,这意味着指针以及原始数组的长度和容量。“这可以用其他语言发生吗?(我想我可能已经用其他语言看到过)”
回答范围太广,有许多种语言,总的来说,如果您有一个指向外界数组的指针,是的。
编辑:
package main
import "fmt"
func sum(a ...int) int {
s := 0
for _, v := range a {
s += v
}
return s
}
func f2(a []int) {
c := make([]int, len(a))
copy(c, a)
c[0] = 50
fmt.Println(sum(c...)) // 52
}
func main() {
b := []int{2, 2}
fmt.Println(sum(1, 2, 3, 4)) // 10
fmt.Println(sum(b...)) // 4
f2(b)
fmt.Println(b) // [2 2]
}
笔记:上面的
sum()
函数是纯函数,因为它没有副作用。上面的新
f2
函数是纯函数,因为它没有副作用:它将a
的副本复制到c
中,然后调用求和。关于go - slice 或数组是否充当全局作用域?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/62645072/