
Go语言的接口是一种抽象类型,它定义了一组方法签名。一个类型只要实现了接口中定义的所有方法,就被认为是实现了该接口,无需显式声明。这种隐式实现机制是Go语言的强大之处。接口关注的是“行为”,即一个类型能够做什么,而不是它是什么。
例如,在提供的代码中,ResourceController 接口定义了四个方法:Show、Create、Update 和 Delete。
type ResourceController interface {
Show(w *rest.ResponseWriter, req *rest.Request)
Create(w *rest.ResponseWriter, req *rest.Request)
Update(w *rest.ResponseWriter, req *rest.Request)
Delete(w *rest.ResponseWriter, req *rest.Request)
}任何类型,只要它拥有这四个方法,并且方法签名完全匹配,就实现了 ResourceController 接口。
在Go语言中,为类型定义方法时,可以选择使用值接收者或指针接收者。这是理解接口实现的关键所在。
立即学习“go语言免费学习笔记(深入)”;
值接收者 (func (v T) Method(...)) 当使用值接收者时,方法操作的是接收者类型的一个副本。这意味着在方法内部对接收者进行的任何修改都不会影响原始值。对于值接收者定义的方法,无论是类型 T 的值还是类型 *T 的指针,都可以调用该方法。因此,如果一个接口的所有方法都由值接收者实现,那么 T 和 *T 都实现了该接口。
*指针接收者 (`func (p T) Method(...)`)** 当使用指针接收者时,方法操作的是接收者类型的一个指针。这意味着在方法内部对接收者进行的修改会影响原始值。指针接收者通常用于:
我们来看原始代码中的 AppController 类型及其方法实现:
type AppController struct{}
func (self *AppController) Show(w *rest.ResponseWriter, r *rest.Request) { /* ... */ }
func (self *AppController) Create(w *rest.ResponseWriter, r *rest.Request) { /* ... */ }
func (self *AppController) Update(w *rest.ResponseWriter, r *rest.Request) { /* ... */ }
func (self *AppController) Delete(w *rest.ResponseWriter, r *rest.Request) { /* ... */ }可以看到,AppController 类型的所有四个方法 (Show, Create, Update, Delete) 都使用了指针接收者 (*AppController)。这意味着,只有 *AppController (即 AppController 的指针类型) 实现了 ResourceController 接口。
然而,在 main 函数中,AppController 的实例化方式如下:
func main() {
handler := MyResourceHandler{}
controler := AppController{} // controler 的类型是 AppController (值类型)
handler.AddResource("app", controler) // 这里将 AppController 值类型传递给需要 ResourceController 的参数
http.ListenAndServe(":9008", &handler)
}当 controler := AppController{} 执行时,controler 被创建为一个 AppController 的值类型实例。随后,这个值类型实例被传递给 handler.AddResource 方法,该方法期望一个 ResourceController 接口类型的参数。
由于 AppController 的所有接口方法都是通过指针接收者实现的,所以 AppController 值类型本身并没有实现 ResourceController 接口。只有 *AppController (指针类型) 实现了该接口。因此,编译器会抛出以下错误:
./fakeapi.go:93: cannot use controler (type AppController) as type ResourceController in function argument:
AppController does not implement ResourceController (Create method requires pointer receiver)这个错误信息明确指出:AppController 类型没有实现 ResourceController 接口,因为其 Create 方法(以及其他方法)需要一个指针接收者。
解决这个问题的方法非常直接:在实例化 AppController 时,应该创建一个其指针类型的实例,因为它才是真正实现了 ResourceController 接口的类型。
将 main 函数中的实例化语句修改为:
func main() {
handler := MyResourceHandler{}
// 修正:使用指针类型来实例化控制器
controler := &AppController{} // 此时 controler 的类型是 *AppController
handler.AddResource("app", controler)
http.ListenAndServe(":9008", &handler)
}通过 controler := &AppController{},我们创建了一个 AppController 类型的指针,其类型为 *AppController。现在,*AppController 正确地实现了 ResourceController 接口,代码将能够顺利编译和运行。
理解Go语言中方法接收者与接口实现之间的微妙关系,是编写健壮、高效Go代码的基础。通过本文的示例,希望能帮助开发者更好地掌握这一核心概念,避免常见的“接口未实现”错误。
以上就是Go语言接口实现深度解析:值接收者与指针接收者的区别的详细内容,更多请关注php中文网其它相关文章!
每个人都需要一台速度更快、更稳定的 PC。随着时间的推移,垃圾文件、旧注册表数据和不必要的后台进程会占用资源并降低性能。幸运的是,许多工具可以让 Windows 保持平稳运行。
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号