请说明golang类型是不是按值传递
Posted
技术标签:
【中文标题】请说明golang类型是不是按值传递【英文标题】:Please explain if golang types pass by value请说明golang类型是否按值传递 【发布时间】:2018-05-09 06:08:18 【问题描述】:我正在尝试制作一个非常简单的程序来修改数组,但是如果我将它们转换为类型,则会遇到一些有趣的行为。 https://play.golang.org/p/KC7mqmHuLw 看来,如果我有一个数组,则按引用传递,但如果我有一个类型,则按值传递。这是正确的吗?
我有两个变量 b 和 c,都是 3 个整数的数组,但 c 是 cT 类型,在其他方面它们应该是相同的。我可以将值分配为b[0]=-1
和c[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 := []int1, 2, 3
c := cT1, 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
【问题讨论】:
好的,感谢您的帮助!根据提供的信息,我通过传递对类型manglePC(&c)
的引用并将函数更改为:func manglePC(row *cT) (*row)[2] = 0
来获得我想要的效果
【参考方案1】:
The Go Programming Language Specification
Array types
数组是单一类型的元素的编号序列,称为 元素类型。
Slice types
切片是底层的连续段的描述符 数组并提供对该数组元素的编号序列的访问 数组。
Calls
在函数调用中,函数值和参数在 通常的顺序。在评估它们之后,调用的参数 通过值传递给函数并且被调用的函数开始 执行。函数的返回参数按值传递 函数返回时返回调用函数。
type cT [3]int b := []int1, 2, 3 c := cT1, 2, 3
我有两个变量,
b
和c
,都是 3 个整数的数组
不,你没有!
b
是 int
的 slice,长度 (len(b)
) 3 和容量 (cap(b)
) 3,c
是 数组 (len(c)
) 3 int
。
在 Go 中,所有参数都是按值传递的。 b
作为切片描述符传递,c
作为数组传递。切片描述符是一个struct
,具有切片长度和容量,以及指向底层数组的指针。
【讨论】:
【参考方案2】:见 cmets:
func main()
b := []int1, 2, 3 // slice
c := cT1, 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)
当我将 slice 称为 ref 时,我在这里简化了细节https://blog.golang.org/go-slices-usage-and-internals
https://play.golang.org/p/OAaCMhc-Ug
【讨论】:
以上是关于请说明golang类型是不是按值传递的主要内容,如果未能解决你的问题,请参考以下文章