Golang中指针方法如何接收值接收器
Golang中指针方法如何接收值接收器 我创建了一个只接受指针的方法,但为什么我仍然能够通过值接收器调用它?
type User struct {
Name string
Email string
}
func (u *User) Notify() {
fmt.Println(u.Name)
}
func main() {
// 尽管是值类型,但工作正常
bill := User{"Bill", "bill@email.com"}
bill.Notify()
jill := &User{"Jill", "jill@email.com"}
jill.Notify()
}
但是当我添加接口时:
package main
func (u *User) Notify() error {
log.Printf("User: Sending User Email To %s<%s>\n",
u.Name,
u.Email)
return nil
}
type Notifier interface {
Notify() error
}
func SendNotification(notify Notifier) error {
return notify.Notify()
}
func main() {
user := User{
Name: "janet jones",
Email: "janet@email.com",
}
SendNotification(user)
}
它开始抛出错误,说我只接受指针,这是为什么???
更多关于Golang中指针方法如何接收值接收器的实战教程也可以访问 https://www.itying.com/category-94-b0.html
2 回复
这是Go语言中方法集(method set)的规则导致的。让我详细解释一下:
方法集规则
在Go中,方法集决定了哪些方法可以被特定类型的值调用:
- 类型
T的方法集包含所有 值接收器 声明的方法 - 类型
*T的方法集包含所有 值接收器 和 指针接收器 声明的方法
你的代码分析
第一个例子能工作的原因
bill := User{"Bill", "bill@email.com"}
bill.Notify() // 这能工作
这里Go编译器自动做了转换,等价于:
(&bill).Notify()
第二个例子失败的原因
func SendNotification(notify Notifier) error {
return notify.Notify()
}
user := User{
Name: "janet jones",
Email: "janet@email.com",
}
SendNotification(user) // 编译错误!
当通过接口调用时,Go不会自动取地址。User 类型的方法集只包含值接收器的方法,而 Notify() 是指针接收器的方法,所以 User 不满足 Notifier 接口。
解决方案
方案1:传递指针
func main() {
user := User{
Name: "janet jones",
Email: "janet@email.com",
}
SendNotification(&user) // 传递指针
}
方案2:使用值接收器
func (u User) Notify() error { // 改为值接收器
log.Printf("User: Sending User Email To %s<%s>\n",
u.Name,
u.Email)
return nil
}
方案3:直接创建指针
func main() {
user := &User{ // 直接创建指针
Name: "janet jones",
Email: "janet@email.com",
}
SendNotification(user)
}
完整工作示例
package main
import (
"log"
)
type User struct {
Name string
Email string
}
func (u *User) Notify() error {
log.Printf("User: Sending User Email To %s<%s>\n",
u.Name,
u.Email)
return nil
}
type Notifier interface {
Notify() error
}
func SendNotification(notify Notifier) error {
return notify.Notify()
}
func main() {
user := User{
Name: "janet jones",
Email: "janet@email.com",
}
// 正确调用方式
SendNotification(&user)
}
记住这个规则:接口调用时不会自动取地址,直接方法调用时会自动转换。


