Golang中指针指示器的设计是否令人困惑?
Golang中指针指示器的设计是否令人困惑? 大家好,
我正在学习指针,注意到在定义指针时我们使用 &a(假设 a 是一个变量),但在函数中使用指针时(无论是作为接收器还是返回类型)却使用 *a。所以,对于刚接触 Go 语言的我来说,感觉这有点令人困惑。你们怎么看?
谢谢
两者都是指针。 因此执行 p:= &a 等同于你可以写成 var p *int = &a
&a 是将变量的地址赋给指针,而不是创建指针。
例如
package main
import (
"fmt"
)
func main() {
a := 1
p := &a
var q *int = &a
fmt.Printf("a=%d, p=%v, q=%v", a, p, q)
}
Yamil_Bracho:
package main import ( "fmt" ) func main() { a := 1 p := &a var q *int = &a fmt.Printf("a=%d, p=%v, q=%v", a, p, q) }
以下是我得到的结果:
a=1, p=0xc000016098, q=0xc000016098
所以p和q是相同的。你认为p不是指针而q是指针吗?
感谢您的快速回复,但这正是我感到困惑的地方。假设 a := 1,然后定义一个指针 p := &a,请注意指针只是一个变量 p,没有任何前缀(没有 *)。当我们进行解引用时,使用 *p 来获取 a 的值。
如果这是正确的,那么在指针前添加前缀 * 就是解引用,它会调用存储在 p 内存地址中的变量值。
所以我的问题仍然是:当我们使用 func (ob *somevariable) () {} 时,使用 * 表示指针不会让人感到困惑吗?
func (ob *somevariable) () {}
在Go语言中,指针的设计遵循C语言的传统,但语法更简洁,理解其逻辑后并不复杂。让我通过示例解释&和*的用法。
1. & 操作符用于获取变量的内存地址(即生成指针):
a := 42
ptr := &a // ptr 现在是一个指向a的指针,类型为 *int
这里,&a 返回变量 a 的内存地址,赋值给指针变量 ptr。
2. * 操作符用于解引用指针(即访问指针指向的值):
fmt.Println(*ptr) // 输出: 42,通过 *ptr 获取 ptr 指向的值
*ptr = 100 // 通过指针修改 a 的值
fmt.Println(a) // 输出: 100
在函数中使用指针时,* 用于声明指针类型或操作指针指向的数据。
3. 函数中的指针示例:
- 作为参数:
func modifyValue(ptr *int) {
*ptr = 200 // 解引用指针并修改值
}
func main() {
x := 10
modifyValue(&x) // 传递 x 的地址
fmt.Println(x) // 输出: 200
}
- 作为返回类型:
func createPointer() *int {
v := 5
return &v // 返回局部变量 v 的指针(Go 逃逸分析处理内存安全)
}
func main() {
p := createPointer()
fmt.Println(*p) // 输出: 5
}
- 作为接收器(在方法中):
type MyStruct struct {
value int
}
func (m *MyStruct) setValue(v int) {
m.value = v // 自动解引用:等价于 (*m).value = v
}
func main() {
obj := MyStruct{value: 1}
obj.setValue(10) // 编译器自动处理为 (&obj).setValue(10)
fmt.Println(obj.value) // 输出: 10
}
在方法接收器中,Go 自动处理指针解引用,无需显式使用 * 访问字段。
总结:
&用于取地址生成指针。*用于声明指针类型或解引用指针。- 初始时可能混淆,但通过实践(如修改函数外变量或避免大结构体复制)会熟悉。Go 的指针设计减少了内存复制并支持共享数据,是高效编程的关键。


