关于这个“ X 不实现 Y(…方法有一个指针接收器) ”的问题已经有几个问答,但对我来说,他们似乎在谈论不同的事情,并不适用于我的具体情况。
所以,我没有让问题变得非常具体,而是让它变得宽泛和抽象——似乎有几种不同的情况会导致这个错误发生,有人可以总结一下吗?
即,如何避免问题,如果发生,有哪些可能性?谢谢。
原文由 xpt 发布,翻译遵循 CC BY-SA 4.0 许可协议
为了保持简短,假设您有一个 Loader 接口和一个实现该接口的 WebLoader。
package main
import "fmt"
// Loader defines a content loader
type Loader interface {
load(src string) string
}
// WebLoader is a web content loader
type WebLoader struct{}
// load loads the content of a page
func (w *WebLoader) load(src string) string {
return fmt.Sprintf("I loaded this page %s", src)
}
func main() {
webLoader := WebLoader{}
loadContent(webLoader)
}
func loadContent(loader Loader) {
loader.load("google.com")
}
上面的代码会给你这个编译时错误
./main.go:20:13: 不能在 loadContent 的参数中使用 webLoader(WebLoader 类型)作为 Loader 类型:WebLoader 没有实现 Loader(Load 方法有指针接收器)
要修复它,您只需将 webLoader := WebLoader{}
更改为以下内容:
webLoader := &WebLoader{}
为什么这会解决这个问题?因为你定义了这个函数 func (w *WebLoader) Load
来接受一个指针接收器。如需更多解释,请阅读@icza 和@karora 的回答
原文由 Saman 发布,翻译遵循 CC BY-SA 4.0 许可协议
7 回答5.3k 阅读
6 回答6.8k 阅读✓ 已解决
4 回答2.3k 阅读
1 回答3.3k 阅读
2 回答2.2k 阅读
1 回答2.1k 阅读
1 回答1.5k 阅读
当您尝试将 具体 类型分配或传递(或转换)为接口类型时,会出现此编译时错误;并且类型本身不实现接口,只是 指向类型 的指针。
简短摘要: 如果 分配 的值实现了分配给它的接口,则对接口类型变量的分配是有效的。如果它的 方法集 是接口的超集,它就会实现它。指针类型的方法集包括 具有 指针和非指针接收器的方法。非指针类型的方法集 只 包括非指针接收者的方法。
让我们看一个例子:
Stringer
接口类型只有一个方法:String()
。存储在接口值Stringer
中的任何值都必须具有此方法。我们还创建了一个MyType
,我们创建了一个带有 指针 接收器的方法MyType.String()
。这意味着String()
方法在*MyType
类型的 方法集中,但不在MyType
的方法集中。当我们尝试将 --- 的值分配给类型为
Stringer
MyType
的变量时,我们得到了有问题的错误:但是,如果我们尝试将 --- 类型的值分配给
Stringer
*MyType
,一切都很好:我们得到了预期的结果(在 Go Playground 上尝试):
所以得到这个编译时错误的要求:
解决问题的可能性:
结构和嵌入
使用 结构和嵌入 时,实现接口(提供方法实现)的通常不是“您”,而是您嵌入到
struct
中的类型。就像在这个例子中:再次,编译时错误,因为
MyType2
的方法集不包含String()
嵌入的方法MyType
方法集*MyType2
,---
,因此以下工作(在 Go Playground 上尝试):我们也可以让它工作,如果我们嵌入
*MyType
并且只使用一个 非指针MyType2
(在 Go Playground 上试试):此外,无论我们嵌入什么(
MyType
或*MyType
),如果我们使用指针*MyType2
尝试,它总是可以工作(地面):规范中的相关部分(来自 Struct types 部分):
所以换句话说:如果我们嵌入了一个非指针类型,那么非指针嵌入器的方法集只会得到带有非指针接收者的方法(来自嵌入类型)。
如果我们嵌入一个指针类型,非指针嵌入器的方法集将获得同时具有指针和非指针接收器的方法(来自嵌入类型)。
如果我们使用指向嵌入器的指针值,无论嵌入类型是否为指针,指向嵌入器的指针的方法集总是获得指针和非指针接收器(来自嵌入类型)的方法。
笔记:
有一个非常相似的情况,即当您有一个包含值
MyType
的接口值时,您尝试从中 键入断言 另一个接口值Stringer
。在这种情况下,由于上述原因,断言将不成立,但我们会得到一个稍微不同的运行时错误:运行时恐慌(在 Go Playground 上尝试):
尝试转换而不是类型断言,我们得到了我们正在谈论的编译时错误: