1

我试图制作一个非常简单的程序来修改数组,但是如果将它们转换为类型,会遇到一些有趣的行为。 https://play.golang.org/p/KC7mqmHuLw看来,如果我有一个数组去传递参考,但如果我有一个类型,然后去传递值。它是否正确?请解释一下golang类型是否按值传递

我有两个变量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 
} 
+0

OK,感谢您的帮助!通过提供的信息,我得到了我想要的效果,通过传递类型'manglePC(&c)'的引用并将函数更改为:func manglePC(row * cT){* row} [2] = 0 }' – SammyO

回答

2

The Go Programming Language Specification

Array types

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

Slice types

切片是用于底层 阵列的连续区段的描述符并提供访问从 数组元素的编号序列。

Calls

在一个函数调用,该函数值和参数在 通常的顺序进行评估。评估完成后,呼叫 的参数将按值传递给函数,被调用的函数将开始执行 。当函数返回时,函数的返回参数通过值 传回给调用函数。


type cT [3]int 

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

我有两个变量,bc,都是3个整数


不,你不数组!

b切片int与长度(len(b))3和容量(cap(b))3,c是(len(c))3 int一个阵列

在Go中,所有参数都按值传递。 b作为切片描述符传递,c作为数组传递。切片描述符是具有切片长度和容量的struct以及指向底层数组的指针。

0

看评论:

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