Golang中解引用指针的方法与技巧
Golang中解引用指针的方法与技巧
下面的代码要求我使用 personPtr.age = personPtr.age + 1。我原本以为需要像这样解引用指针 *personPtr.age = *personPtr.age + 1,但编译器对后一种写法报错。为什么我不需要解引用指针呢?
package main
import (
"fmt"
)
type person struct {
name string
age int
}
func happyBirthday(personPtr *person) {
personPtr.age = personPtr.age + 1
}
func main() {
youngMonkey := person{name: "YoungMonkey", age: 0}
happyBirthday(&youngMonkey)
fmt.Println(youngMonkey.age)
}
更多关于Golang中解引用指针的方法与技巧的实战教程也可以访问 https://www.itying.com/category-94-b0.html
顺便提一下,如果你这样做:
func happyBirthday(personPtr *person) {
(*personPtr).age = (*personPtr).age + 1
}
它是有效的。
我原以为我需要像这样解引用指针
*personPtr.age = *personPtr.age + 1,但编译器对后一种选项报错。为什么我不需要解引用指针呢?
Go 在其规范中为结构体数据类型执行自动解引用。因此,您不需要显式地解引用它。引用如下:
与选择器一样,使用指针引用具有值接收器的非接口方法将自动解引用该指针:
pt.Mv等价于(*pt).Mv。(更多信息请参阅:Go 编程语言规范 - Go 编程语言, Go 编程语言规范 - Go 编程语言)
只有当您将切片、映射或数组作为指针传递时(这种情况很少见,但那是另一个问题),才需要解引用。例如:
func myProcess(a *map[string]string) {
t := (*a)["whatever"]
...
}
在Go语言中,当通过结构体指针访问其字段时,编译器会自动进行解引用,无需显式使用*操作符。这是Go语言设计的一个便利特性,使得指针操作更加简洁。
在您的代码中,personPtr.age实际上等价于(*personPtr).age。编译器在遇到指针类型的结构体访问字段时,会自动插入解引用操作。
如果您尝试使用*personPtr.age,编译器会将其解析为*(personPtr.age),这会导致错误,因为:
.操作符的优先级高于*操作符personPtr.age已经是一个整数值,不能再对其进行解引用
以下是正确的显式解引用写法:
func happyBirthday(personPtr *person) {
(*personPtr).age = (*personPtr).age + 1
}
但Go语言推荐使用您原来的简洁写法。编译器会将这两种写法编译为相同的机器代码。
为了更清楚地展示这个特性,这里有一个完整的示例:
package main
import "fmt"
type person struct {
name string
age int
}
func happyBirthday(personPtr *person) {
// 以下三种写法都是等价的,都能正常工作:
// 1. 简洁写法(推荐)
personPtr.age = personPtr.age + 1
// 2. 显式解引用
(*personPtr).age = (*personPtr).age + 1
// 3. 使用括号明确优先级
(*personPtr).age = (*personPtr).age + 1
}
func main() {
p := &person{name: "YoungMonkey", age: 0}
fmt.Printf("Before: %d\n", p.age) // 输出: Before: 0
happyBirthday(p)
fmt.Printf("After: %d\n", p.age) // 输出: After: 1
fmt.Printf("Direct access: %d\n", (*p).age) // 输出: Direct access: 1
}
这种自动解引用的特性同样适用于嵌套结构体:
type Address struct {
city string
}
type Employee struct {
name string
address *Address
}
func updateCity(emp *Employee) {
// 以下两种写法等价
emp.address.city = "Shanghai"
(*emp).address.city = "Shanghai"
}
需要注意的是,这种自动解引用只适用于结构体指针访问字段的情况。对于其他类型的指针操作,仍然需要显式使用*操作符:
func increment(n *int) {
*n = *n + 1 // 这里必须使用显式解引用
}
总结:Go语言在设计时特意让结构体指针访问字段的语法更加简洁,这是语言的一个特性而非bug。编译器在背后处理了必要的解引用操作。


