Golang指针问题:仅有4小时经验如何理解

Golang指针问题:仅有4小时经验如何理解

package main

import "fmt"

type person struct {
	firstName string
	lastName  string
}

func printPerson(p person) {
	fmt.Println(p)
}
func (pointerToPerson *person) updatePerson(newFirstName string) {
	newPerson := *pointerToPerson
	fmt.Println(newPerson)
	newPerson.firstName = newFirstName
	fmt.Println(newPerson)
}

func main() {
	bobuGeorge := person{"Bobu", "George"}
	bobuGeorge.updatePerson("Bob")
	printPerson(bobuGeorge)

}

为什么原始’person’没有被更新? 如果我使用(*pointerToPerson),原始person就会被更新


更多关于Golang指针问题:仅有4小时经验如何理解的实战教程也可以访问 https://www.itying.com/category-94-b0.html

3 回复

结构体通常按值传递。所以你的这行代码:

newPerson := *pointerToPerson

创建了一个 Person 类型的新结构体,它是指针 pointerToPerson 所指向的 Person 对象的副本

一个简单的"修复"程序的方法是将这行代码改为:

newPerson := pointerToPerson

这意味着创建一个新的指向 person 的指针,并让它指向与 pointerToPerson 相同的结构体

更多关于Golang指针问题:仅有4小时经验如何理解的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


updatePersonperson 的一个方法pointerToPerson 是该方法的接收器

期望操作接收器的方法直接执行如下:

func (pointerToPerson *person) updatePerson(newFirstName string) {
	pointerToPerson.firstName = newFirstName
}

https://play.golang.org/p/Oy7pXbVwEvL

在你的代码中,问题出现在方法 updatePerson 的实现方式上。当你使用 newPerson := *pointerToPerson 时,你创建了一个结构体的副本,而不是直接操作原始数据。因此,对副本的修改不会影响原始变量。

以下是详细解释和修正后的代码:

问题分析

  • updatePerson 方法中,newPerson := *pointerToPerson 解引用指针,但将结果赋值给一个新变量 newPerson。这创建了一个原始结构的独立副本。
  • 随后修改 newPerson.firstName 只影响这个副本,原始 person 保持不变。
  • 当你使用 (*pointerToPerson).firstName = newFirstName 时,你直接通过指针修改了原始数据,因此更新会生效。

修正后的代码

要更新原始 person,你应该直接通过指针操作字段,而不是创建副本。以下是修正后的示例:

package main

import "fmt"

type person struct {
    firstName string
    lastName  string
}

func printPerson(p person) {
    fmt.Println(p)
}

func (pointerToPerson *person) updatePerson(newFirstName string) {
    // 直接通过指针更新字段,避免创建副本
    (*pointerToPerson).firstName = newFirstName
}

func main() {
    bobuGeorge := person{"Bobu", "George"}
    bobuGeorge.updatePerson("Bob")
    printPerson(bobuGeorge) // 输出: {Bob George}
}

简化指针语法

在Go中,你可以省略显式的指针解引用,直接使用指针访问字段。编译器会自动处理。这是更常见的写法:

func (pointerToPerson *person) updatePerson(newFirstName string) {
    pointerToPerson.firstName = newFirstName // 等效于 (*pointerToPerson).firstName
}

关键点

  • 指针允许你直接操作内存中的数据。在方法中,如果接收者是指针类型,修改会反映到原始变量上。
  • 创建副本(如通过赋值)会断开与原始数据的链接,导致修改无效。

通过这个修正,原始 person 会被正确更新为 {Bob George}

回到顶部