Menu
CoddyTech

值与引用

Coddy Golang 中的函数和指针 课程的第 7 课,共 19 课。

到目前为止,我们已经学习了如何使用函数的参数和返回值。本课将介绍另一个在使用函数时需要了解的重要概念。

来看这样一个程序:

func main() {
    a := 5
    fmt.Println("value of a:", a)
    sum(a)
    fmt.Println("value of a after addition:", a)
}
func sum(x int) {
    x = x + x
}

在这个程序中,我们声明了变量 a,打印它的值,然后把它传给名为 sum 的函数。这个函数会执行加法 5 + 5。你觉得这段代码会得到什么结果?

我们运行一下看看:

value of a: 5
value of a after addition: 5

值没有变化。这里有个问题,调用 sum 函数后,a 应该变成 10,对吧?

其实不是,因为在 Go 中,把值传给函数时,传递的只是它的副本。修改这个值时,函数外部不会受到影响,值只会在函数内部改变。我们可以在 sum 函数内部打印这个值来验证:

func main() {
    a := 5
    fmt.Println("value of a:", a)
    sum(a)
    fmt.Println("value of a after addition:", a)
}
func sum(x int) {
    x = x + x
    fmt.Println("value inside the function:", x)
}

运行后,我们会得到:

value of a: 5
value inside the function: 10
value of a after addition: 5

这意味着值在函数内部会改变(函数作用域内),但在函数外部,值不会改变。

我知道你需要更多细节才能理解。来看看这张图:

现在明白了吧。这样会创建一个地址不同的新变量(这对内存来说也不好!)。

这就是我们看不到变化的原因,因为这些变量并不相同😅。

要解决这个问题,我们可以使用指针,而不是传递值的副本,例如:

func main() {
    a := 5
    fmt.Println("value of a:", a)
    sum(&a)
    fmt.Println("value of a after addition:", a)
}
func sum(x *int) {
    *x += *x
}

现在,我们传递的不是值,而是内存地址 sum(&a)。这意味着函数会操作同一个变量,而不会创建新变量。

 

challenge icon

挑战

简单

在给定的代码中,我们定义了一个用于交换两个值的函数。请补全代码,让函数正常工作并得到结果。

亲手试试

package main

import "fmt"


func swapValues(a, b int) {
	
  a, b = b, a
}

func main() {
	var x, y int = 4,10

	fmt.Println("Before swap:")
	fmt.Println("x =", x)
	fmt.Println("y =", y)

	swapValues(x, y)

	fmt.Println("After swap:")
	fmt.Println("x =", x)
	fmt.Println("y =", y)
}

Golang 中的函数和指针中的所有课

自己练习: Go 在线编译器