请解释 golang 类型是否按值传递

Please explain if golang types pass by value

提问人:SammyO 提问时间:11/25/2017 最后编辑:SammyO 更新时间:11/25/2017 访问量:6274

问:

我正在尝试制作一个非常简单的程序来修改数组,但是如果我将它们转换为类型,会遇到一些有趣的行为。https://play.golang.org/p/KC7mqmHuLw似乎如果我有一个数组,go 通过引用传递,但如果我有一个类型,那么 go 通过值传递。这是正确的吗?

我有两个变量 b 和 c,它们都是 3 个整数的数组,但 c 是 cT 类型,在其他方面它们应该是相同的。我可以将值赋值为 和 ,但是如果我将这些数组作为参数传递给函数,它们的行为就会大不相同。b[0]=-1c[0]=-1

程序的输出为:

前 B: [1 2 3]

前 c: [1 2 3]

*B后:[-1 2 0]

*C后:[-1 2 3]

*什么?C:[-1 2 0]

我最初的假设是,“在 b 之后”和“在 c 之后”的行应该是相同的。我是否做错了什么,或者我是否正确地将类型传递给通过值传递给函数(即在传递给函数之前创建变量的副本)?

package main

import "fmt"

type cT [3]int

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

    fmt.Println("before b:", b)
    fmt.Println("before c:", c)

    b[0] = -1
    c[0] = -1
    mangleB(b) // ignore return value
    mangleC(c) // ignore return value

    fmt.Println("*after b:", b)
    fmt.Println("*after c:", c)

    c = mangleC(c)    
    fmt.Println("*what? c:", c)    
}

func mangleB(row []int) []int {
    row[2] = 0
    return row
}

func mangleC(row cT) cT{
    row[2] = 0
    return row
}
go 参数传递 引用 传递指针

评论

0赞 SammyO 11/25/2017
好的,谢谢你的帮助!根据提供的信息,我通过传递对类型的引用并将函数更改为:manglePC(&c)func manglePC(row *cT) { (*row)[2] = 0 }

答:

6赞 peterSO 11/25/2017 #1

Go 编程语言规范

数组类型

数组是单一类型的元素的编号序列,称为 元素类型。

切片类型

切片是基础的连续段的描述符 数组,并提供对来自该元素的编号序列的访问 数组。

调用

在函数调用中,函数值和参数的计算结果为 通常的顺序。评估后,调用的参数 按值传递给函数,然后调用函数开始 执行。函数的返回参数按值传递 当函数返回时,返回到调用函数。


type cT [3]int

b := []int{1, 2, 3}
c := cT{1, 2, 3}

我有两个变量,并且 都是 3 个整数的数组bc


不,你没有!

b是长度为 () 3 且容量为 () 3 的切片,是 () 3 的数组intlen(b)cap(b)clen(c)int

在 Go 中,所有参数都是按值传递的。 作为切片描述符传递,作为数组传递。切片描述符是具有切片长度和容量的 a,以及指向基础数组的指针。bcstruct

评论

0赞 Prime624 6/17/2023
切片描述符不是引用吗,这意味着传递切片描述符就是传递引用?
0赞 k1m190r 11/25/2017 #2

查看评论:

func main() {
    b := []int{1, 2, 3} // slice
    c := cT{1, 2, 3} // array

    fmt.Println("before b:", b) 
    fmt.Println("before c:", c) 

    b[0] = -1
    c[0] = -1

    // passing in a slice which you can think of as ref to array
    // pass by value, and it is copy of ref to array 
    mangleB(b) // ignore return value

    // passing in copy of array (pass by value)
    // yes full shallow copy of array 
    mangleC(c) // ignore return value
    // if you ignore return modifications are lost

    fmt.Println("*after b:", b)
    fmt.Println("*after c:", c)

    // return value is modified array
    c = mangleC(c)
    // c now copy of array from line 24

    fmt.Println("*what? c:", c)
}

https://play.golang.org/p/OAaCMhc-Ug