Golang中关于接口和结构的疑问
Golang中关于接口和结构的疑问
你好,我是一名正在学习 Go 语言的计算机工程专业学生。
我有一个关于我的代码的问题。
每次调用函数 foo() 时,其结果都会不断变化。
我无法理解为什么结构体 str 中字段 s 的地址一直在变化。
有人遇到过这种情况吗?
import "fmt"
type str struct {
s int
t int
r int
}
type str2 struct {
s string
t string
r string
}
type inter_face interface {
foo()
}
func (s str) foo() {
fmt.Println("Print")
}
func (s str2) foo() {
fmt.Printf("%v\t%T\t\t\n", &s.r, s)
}
func main() {
var i inter_face
a := str{
s: 100,
t: 1000,
r: 10000,
}
b := str2{
s: "string",
t: "string type",
r: "string bool",
}
i = a
i.foo()
i.foo()
i = b
i.foo()
i.foo()
i.foo()
i.foo()
i.foo()
i.foo()
}
更多关于Golang中关于接口和结构的疑问的实战教程也可以访问 https://www.itying.com/category-94-b0.html
2 回复
你写的两个方法都是通过值传递其接收者参数 s 的。因此,每次调用时它都会被复制并获得一个新的地址。通常方法会通过引用来调用它们的接收者。试试这个:
func (s *str)foo()…
更多关于Golang中关于接口和结构的疑问的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
这是一个关于Go语言中方法接收者和接口实现的常见问题。你观察到的地址变化是因为方法接收者是按值传递的。
在你的代码中,str2 的 foo() 方法接收的是值接收者:
func (s str2) foo() {
fmt.Printf("%v\t%T\t\t\n", &s.r, s)
}
每次调用 i.foo() 时,Go都会创建一个新的 str2 结构体副本,因此 s.r 的地址每次都会不同。让我们通过一个更清晰的示例来说明:
package main
import "fmt"
type str2 struct {
s string
t string
r string
}
type inter_face interface {
foo()
}
// 值接收者 - 每次调用都会创建新副本
func (s str2) foo() {
fmt.Printf("值接收者 - 地址: %p, r地址: %p\n", &s, &s.r)
}
// 指针接收者 - 使用相同的实例
func (s *str2) foo2() {
fmt.Printf("指针接收者 - 地址: %p, r地址: %p\n", s, &s.r)
}
func main() {
var i inter_face
b := str2{
s: "string",
t: "string type",
r: "string bool",
}
// 使用值接收者
fmt.Println("使用值接收者:")
i = b
for j := 0; j < 3; j++ {
i.foo()
}
// 使用指针接收者
fmt.Println("\n使用指针接收者:")
i = &b
for j := 0; j < 3; j++ {
i.foo()
}
// 直接调用对比
fmt.Println("\n直接调用对比:")
fmt.Printf("原始结构体地址: %p\n", &b)
b.foo() // 值接收者
(&b).foo2() // 指针接收者
}
输出会显示:
- 使用值接收者时,每次调用都会创建新的副本,地址不同
- 使用指针接收者时,操作的是同一个实例,地址相同
如果你想让所有调用都操作同一个实例,应该使用指针接收者:
func (s *str2) foo() {
fmt.Printf("%v\t%T\t\t\n", &s.r, s)
}
// 在main中需要传递指针
i = &b
这就是为什么你看到 s.r 地址不断变化的原因 - 每个方法调用都在操作不同的结构体副本。

