接口持有值类型时fmt.Println未调用指针接收者String方法的行为是否符合预期?
接口持有值类型时fmt.Println未调用指针接收者String方法的行为是否符合预期?
这完全是符合Go语言预期的行为,咱们一步步拆解背后的原因:
首先看你代码里的核心细节:你给*User指针类型定义了String()方法,而不是User值类型。在Go的接口规则里,接口要调用某个方法,必须是它持有的具体类型实现了该方法。
当你把u1 := User{name: "old", age: 12}这个值类型变量传给fmt.Println时,any(空接口)里存储的是User的一个值副本。而User值类型并没有实现fmt.Stringer接口——只有*User指针类型才实现了这个接口。所以fmt包在检查当前接口值的时候,找不到对应的String()方法,就会回退到默认的结构体格式化逻辑,也就是直接打印结构体的字段内容,得到{old 12}这个结果。
你可以通过两个小修改来验证这个逻辑:
- 把变量改成指针类型:
这时候u1 := &User{ name: "old", age: 12, } fmt.Println(u1)any接口里存储的是*User指针,能找到对应的String()方法,打印结果就会变成name = old, age = 12。 - 把
String()方法改成值接收者:
这时候func (u User) String() string { return fmt.Sprintf("name = %s, age = %d", u.name, u.age) }User值类型也实现了fmt.Stringer接口,不管传值还是指针给fmt.Println,都会调用自定义的String()方法。
你之前的假设“Pointer receiver methods can't be called on value holding interfaces”是完全正确的,这正是导致当前现象的核心原因——接口持有的是值,而指针接收者的方法属于指针类型,值类型“没有”这个方法,自然就不会被调用啦。
备注:内容来源于stack exchange,提问作者tusharRawat
相关产品推荐
相关产品推荐

