Golang实战练习:指针与解引用的使用
Golang实战练习:指针与解引用的使用 https://play.golang.org/p/L5y0DirzyvK
为什么在这里要使用"changeMe(&p1)"来调用指针?这样做的原因和目的是什么?
3 回复
因为函数接受指针是为了能够修改其指向的变量。正如在其他主题中提到的,在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)调用函数是为了传递变量的内存地址(即指针),而不是传递变量的副本。这样做的主要目的是允许函数直接修改原始变量的值,而不是操作副本。
原因和目的:
- 避免值拷贝:当传递大型结构体时,通过指针传递可以避免内存复制,提高性能。
- 修改原始数据:函数内部对指针的解引用操作(如
*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语言中实现引用传递和避免不必要复制的标准做法。


