Golang实战练习:指针与解引用的使用

Golang实战练习:指针与解引用的使用 https://play.golang.org/p/L5y0DirzyvK

为什么在这里要使用"changeMe(&p1)"来调用指针?这样做的原因和目的是什么?

3 回复

“通过值传递,这意味着函数会获得你传递给它的任何内容的副本,因此在函数内部进行的任何局部修改都不会影响原始变量。为了能够修改变量,我们传递指向它的指针,即它的地址,因为这样函数可以解引用指针并获取原始变量并进行更改。”

这完全说得通。老师告诉我们Go中的所有内容都是"通过值传递"的,但没有给出这个概念的定义,我当时不知道这是什么意思,也不知道该如何提问。所以你可以放心,我会保存这些信息。我是一个需要明确词语和概念定义的人。

此外,这是一个非常有趣且有用的修改。

更多关于Golang实战练习:指针与解引用的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


因为函数接受指针是为了能够修改其指向的变量。正如在其他主题中提到的,在Go语言中参数是按值传递的,这意味着函数获取的是你传递给它的任何内容的副本,因此函数内部的任何局部修改都不会影响原始变量。为了能够修改变量,我们传递指向它的指针,即其地址,这样函数就可以解引用指针并获取原始变量进行修改。

请看基于你的示例稍作修改的版本,我添加了一个接受 person 而非指针的函数,观察调用时它如何不修改 p1,而你原始的函数却可以:https://play.golang.org/p/TNMag0Nvved

func main() {
    p1 := person{"James"}
    fmt.Println(p1)
    changeMe(&p1)
    fmt.Println(p1)
    
    p2 := person{"John"}
    fmt.Println(p2)
    // 此函数接收值而非指针
    changeMeByValue(p2)
    fmt.Println(p2)
}

type person struct {
    name string
}

func changeMe(p *person) {
    p.name = "Miss Moneypenny"
}

// 此函数接收person值
func changeMeByValue(p person) {
    p.name = "值传递不会改变原始变量"
}

在Go语言中,使用changeMe(&p1)调用函数是为了传递变量的内存地址(即指针),而不是传递变量的副本。这样做的主要目的是允许函数直接修改原始变量的值,而不是操作副本。

原因和目的:

  1. 避免值拷贝:当传递大型结构体时,通过指针传递可以避免内存复制,提高性能。
  2. 修改原始数据:函数内部对指针的解引用操作(如*p)可以直接修改原始变量的内容。

示例代码分析:

假设有以下结构体和函数:

package main

import "fmt"

type Person struct {
    Name string
    Age  int
}

// 函数接收指针参数,可以修改原始Person对象
func changeMe(p *Person) {
    p.Name = "Updated Name" // 等价于 (*p).Name = "Updated Name"
    p.Age = 30
}

func main() {
    p1 := Person{Name: "John", Age: 25}
    fmt.Println("Before:", p1) // 输出: Before: {John 25}
    
    changeMe(&p1) // 传递p1的地址
    fmt.Println("After:", p1)  // 输出: After: {Updated Name 30}
}

关键点:

  • &p1获取变量p1的地址,类型为*Person
  • changeMe函数中,通过指针p直接修改了p1的字段值。
  • 如果不使用指针,函数将接收p1的副本,修改不会影响原始变量。

对比无指针的情况:

func changeMeCopy(p Person) {
    p.Name = "Updated Name" // 仅修改副本,原始p1不变
}

func main() {
    p1 := Person{Name: "John", Age: 25}
    changeMeCopy(p1)
    fmt.Println(p1) // 输出: {John 25},未改变
}

因此,在需要修改函数外部变量时,必须传递指针(使用&操作符获取地址)。这是Go语言中实现引用传递和避免不必要复制的标准做法。

回到顶部