Go 将指针或副本的参数传递给函数

Go 将指针或副本的参数传递给函数,go,Go,我正在考虑使用指针,通过值或引用将变量作为参数传递给函数。在一本书中,我遇到了一个很好的例子,这是下面关于传递指针的第一个代码片段 第一个版本按预期工作,在函数中,接受指针的参数对变量本身进行更改,而不是对其副本进行更改。但是下面的第二个例子我正在修改它的副本。我认为它们的行为应该是等价的,第二个应该处理作为参数传递的变量,而不是它的副本 本质上,函数的这两个版本的行为有什么不同 ,通过引用传递参数: package main import ( "fmt" ) // simple fu

我正在考虑使用指针,通过值或引用将变量作为参数传递给函数。在一本书中,我遇到了一个很好的例子,这是下面关于传递指针的第一个代码片段

第一个版本按预期工作,在函数中,接受指针的参数对变量本身进行更改,而不是对其副本进行更改。但是下面的第二个例子我正在修改它的副本。我认为它们的行为应该是等价的,第二个应该处理作为参数传递的变量,而不是它的副本

本质上,函数的这两个版本的行为有什么不同

,通过引用传递参数:

package main

import (
    "fmt"
)
// simple function to add 1 to a
func add1(a *int) int {
    *a = *a+1 // we changed value of a
    return *a // return new value of a
}

func main() {
    x := 3

    fmt.Println("x = ", x)  // should print "x = 3"

    x1 := add1(&x)  // call add1(&x) pass memory address of x

    fmt.Println("x+1 = ", x1) // should print "x+1 = 4"
    fmt.Println("x = ", x)    // should print "x = 4"
}
,传递指针参数:

package main

import (
    "fmt"
)
// simple function to add 1 to a
func add1(a int) int {
    p := &a
    *p = *p+1 // we changed value of a
    return *p // return new value of a
}
func main(){
    fmt.Println("this is my go playground.")

        x := 3

        fmt.Println("x = ", x)  // should print "x = 3"

        x1 := add1(x)  // call add1(&x) pass memory address of x

        fmt.Println("x+1 = ", x1) // should print "x+1 = 4"
        fmt.Println("x = ", x)    // should print "x = 4"   
}

为什么他们的行为应该相当?在第一个示例中,传递指向int的指针,在第二个示例中,传递int值

在第二个示例中,传递一个int值。函数中的参数与局部变量类似。将创建一个名为int类型的局部变量,并使用传递的值3(x的值)进行初始化。这个局部变量和其他变量一样可以寻址

取其地址p:=&a,然后递增该指针指向的值,该指针本身就是变量a。然后返回它所指向的值,即a的增量值

在调用此add1函数的地方之外,没有修改x的值,因为只修改了本地副本a。

golang中的所有内容都是按值传递的,这意味着该函数始终获取所传递内容的副本。 在第二个示例中,x的值实际上被发送到函数add,因此对副本所做的任何修改都不会影响原始x


请参见

注意,在您的版本中,当您执行p:=&a时,您得到的是a的引用,它是x的副本,而不是x的引用。想象一下。你有一幅画。参考图纸,你就得到了这张纸。对纸张执行擦除、绘制等操作会更改图形。现在,复印那张图纸。参考得到图纸的副本,但对该图纸执行操作只会更改副本,而不会更改原始图形。这就是按值传递的含义。Go绝对没有按引用传递的概念。停止使用这个术语,停止思考这些破碎的概念和谈话/思考/使用指针,一切都很好。永远不要将指针参数视为按引用传递。不是。@slebetman p:=&a正在给p分配a的地址,并创建一个指针。它不以任何方式、形状或形式作为参考。a是x的副本