Golang将数组传递给函数并对其进行修改 [英] Golang passing arrays to the function and modifying it

查看:487
本文介绍了Golang将数组传递给函数并对其进行修改的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在大多数语言(如c ++)中,传递数组会导致通过引用隐式传递它,所以对函数中传递数组的任何更改都会导致更改原始数组。我正在学习Golang,并且在Alan A.A.的书The Go Programming Language中。 Donovan和Brian W. Kernighan据说,它的行为与其他语言不同 - 它不会隐式地通过引用传递数组。



这让我有些困惑 - 这并不意味着传递没有引用的数组不应该修改数组本身?让我说明一下:

  func main(){
tab:= [] int {1,2,3 }
fmt.Println(标签)
//结果为[1 2 3]
反向(标签)
fmt.Println(标签)
//结果[3 2 1]
}

func reverse(tab [] int){
for i,j:= 0,len(tab)-1;我<焦耳; i,j = i + 1,j-1 {
tab [i],tab [j] = tab [j],tab [i]
}
}

在上面的代码中,数组没有被引用传递,但是反向函数修改了原始数组,所以它的工作原理与C ++程序会做。任何人都可以解释我的区别吗?



PS:对不起,如果这是一个虚拟问题,我完全不熟悉Golang并试图很好地理解基础知识。 >

解决方案

解释相当简单:没有一个 array 在上面的代码中明确声明或使用。您的选项卡本地变量和选项卡参数为 slices

在Go中,数组的长度是键入,例如 [3] int (例如 [2] int [3] int 是2种不同/不同的数组类型)。如果长度不存在(或者显式为 [2] int 或者隐式类似于复合文字 [...] int {1,2,3} ),那么这不是数组类型,但是一个切片类型。

是的,当你读到的时候,数组的值意味着它的所有元素,当它传递(或赋值)时,它的所有元素都被复制。然而,切片只是小描述符,标题,描述数组的连续部分;并且当切片传递(或分配)时,只有这个标题被复制(包含指针),它将指向相同的基础数组。因此,如果修改切片副本的元素,则更改将反映在原始切片中,因为只有一个支持元素的后备数组。



< sup>如果您想完全知道切片标题中的内容,可以查看 reflect.SliceHeader 类型:它是一个 struct ,包含指向片的第一个元素的指针,长度和容量。请阅读以下博客文章,详细解释这一点:

$ b $

b

切片:使用和内部

数组,片段(和字符串): 'append'



有关更多详细信息,请参阅这些相关问题:

为什么有数组在Go?



golang切片传递的价值?


In most languages (like c++) passing arrays result in implicitly passing it by a reference, so any changes to the passed array in the function will result in changing the original one. I am learning Golang, and In the book "The Go Programming Language" by Alan A.A. Donovan and Brian W. Kernighan It is said, that its behaviour is different from other languages - It does not implicitly pass array by reference.

It is confusing me a bit - doesn't that mean that passing an array without the reference should not modify the array itself? Let me illustrate that:

func main() {
    tab := []int{1, 2, 3}
    fmt.Println(tab)
    // Results in [1 2 3]
    reverse(tab)
    fmt.Println(tab)
    // Results in [3 2 1]
}

func reverse(tab []int) {
    for i, j := 0, len(tab)-1; i < j; i, j = i+1, j-1 {
        tab[i], tab[j] = tab[j], tab[i]
    }
}

In code above array is not passed by the reference, but the reverse function modifies the original one, so It works somewhat like C++ program would do. Could anyone explain me the difference?

PS: Sorry if it is a dummy question, I am totally new to the Golang and trying to understand the basics well.

解决方案

The explanation is rather simple: there isn't a single array declared or used explicitly in your code above. Your tab local variable and the tab parameter are slices.

In Go the length of an array is part of the type, e.g. [3]int (this is true to an extent that for example [2]int and [3]int are 2 different / distinct array types). If the length is not present (either explicit like [2]int or implicit like in the composite literal [...]int{1, 2, 3}), then that is not an array type but a slice type.

Yes, as you read, an array value means all its elements, and when passed around (or assigned), all its elements are copied. Slices however are just small descriptors, headers, describing a contiguous section of an array; and when slices are passed around (or assigned), only this header is copied (the pointer included), which will point to the same underlying array. And so if you modify the elements of the slice-copy, the changes will be reflected in the original slice as there is only one backing array that holds the elements.

If you want to know what's in a slice header exactly, you may check out the reflect.SliceHeader type: it's a struct containing the pointer to the first element of the slice, the length and the capacity of the slice.

Please read the following blog posts which explain this in great details:

Go Slices: usage and internals

Arrays, slices (and strings): The mechanics of 'append'

Also see these related questions for more details:

Why have arrays in Go?

Are golang slices pass by value?

这篇关于Golang将数组传递给函数并对其进行修改的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆