关于“ X不能实现Y(…方法具有指针接收器) ”的事情已经有一些问答,但是对我来说,他们似乎在谈论不同的事情,而不适用于我的具体情况。
因此,我没有使问题变得非常具体,而是使之变得笼统和抽象-似乎有几种不同的情况可以使此错误发生,请有人总结一下吗?
即,如何避免该问题,如果发生,可能性是什么?谢谢。
当您尝试将 具体 类型分配或传递(或转换)为接口类型时,会出现此编译时错误。并且类型本身不实现接口,仅实现 指向type 的 指针 。
让我们来看一个例子:
type Stringer interface {
String() string
}
type MyType struct {
value string
}
func (m *MyType) String() string { return m.value }
该Stringer
接口类型只有一个方法:String()
。接口值中存储的任何值都Stringer
必须具有此方法。我们还创建了一个MyType
,并创建了一个MyType.String()
带有
指针
接收器的方法。这意味着String()
方法在方法集合的的*MyType
类型,但不是在的MyType
。
当我们尝试将值MyType
赋给type的变量时Stringer
,我们得到了相关的错误:
m := MyType{value: "something"}
var s Stringer
s = m // cannot use m (type MyType) as type Stringer in assignment:
// MyType does not implement Stringer (String method has pointer receiver)
但是,如果我们尝试将type的值分配*MyType
给Stringer
:
s = &m
fmt.Println(s)
我们得到了预期的结果(在Go Playground上尝试):
something
因此,获取此编译时错误的要求:
解决此问题的可能性:
使用结构和嵌入时,实现接口的通常不是“您”(提供方法实现),而是嵌入到中的类型struct
。像这个例子一样:
type MyType2 struct {
MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: m}
var s Stringer
s = m2 // Compile-time error again
再次出现编译时错误,因为的方法集MyType2
不包含String()
EmbeddedMyType
的方法,仅包含的方法集*MyType2
,因此以下工作(在GoPlayground上尝试):
var s Stringer
s = &m2
如果我们*MyType
仅嵌入并使用 非指针 ,也可以使其工作MyType2
(在GoPlayground上尝试):
type MyType2 struct {
*MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: &m}
var s Stringer
s = m2
另外,无论我们嵌入什么(MyType
或*MyType
),如果我们使用指针*MyType2
,它将始终有效(在Go
Playground
上尝试):
type MyType2 struct {
*MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: &m}
var s Stringer
s = &m2
规范中的相关部分(来自“ 结构类型”部分):
给定一个结构类型
S
和一个名为的类型T
,在该方法的方法集中包括了提升的方法,如下所示:
- 如果
S
包含匿名字段T
,则S
和的方法集*S
都将包含带有接收器的升级方法T
。方法集*S
还包括带有接收方的提升方法*T
。- 如果
S
包含匿名字段*T
,则S
和的方法集*S
都将包含带有接收者T
或的升级方法*T
。
所以换句话说:如果我们嵌入一个非指针类型,则非指针嵌入器的方法集只能获取带有非指针接收器的方法(来自嵌入式类型)。
如果我们嵌入一个指针类型,则非指针嵌入器的方法集将获得同时具有指针和非指针接收器的方法(来自嵌入式类型)。
如果我们使用指向嵌入器的指针值,则不管嵌入的类型是否为指针,指向嵌入器的指针的方法集总是获取带有指针和非指针接收器的方法(来自嵌入类型)。
注意:
有一种非常相似的情况,即当您有一个包装了值的接口值MyType
,并尝试从中键入assert另一个接口值时Stringer
。在这种情况下,由于上述原因该断言将不成立,但是我们会得到一个稍微不同的运行时错误:
m := MyType{value: "something"}
var i interface{} = m
fmt.Println(i.(Stringer))
运行时恐慌(在Go Playground上尝试):
panic: interface conversion: main.MyType is not main.Stringer:
missing method String
尝试转换而不是类型断言,我们得到了我们正在谈论的编译时错误:
m := MyType{value: "something"}
fmt.Println(Stringer(m))
问题内容: ./chains.go:26:10:不能在作业中使用UpperCaseHandler(typefunc(asl.MessageDelivery))作为asl.MessageHandler类型./chains.go:37:86:无法使用RepeatHandler(类型func(asl.MessageDelivery))与Repeater.ConsumeFunc的参数中的asl.Messa
这是我的水果 现在我正在导入另一个typescript文件中的fruit.ts。这是我的 当我做的时候 我得到一个错误: 类型“string”不能分配给类型“orange”“apple”“banana”“ 如何将字符串赋给自定义类型fruit的变量?
在我的班级中,我有一个属性: 并希望将其设置为: 设置此设置时,我会得到错误
问题内容: 我正在尝试通过符合协议的编码模型来获取数据。但是它无法像下面的代码那样调用func : 但是在另一个演示中,效果很好,为什么呢? 问题答案: 解决方案1。 https://github.com/satishVekariya/SVCodable 试试这个代码,它扩展了可编码 解决方案2。 避免污染带有扩展名的Apple提供的协议 用
这是一个类中的函数,允许你双击和单击手势。它在Swift 2.3中运行良好,但在转换到Swift 3后,它抛出了一些错误。我怎么也想不明白。我评论了它们发生的地方。
问题内容: 抱歉,标题似乎令人困惑,但请按示例进行操作。 假设我有一些带有通用类型参数的Java类: 我可以创建一个类型为存储对象的变量,并将通用参数设置为。Java还允许我将该变量分配给另一个变量,但将通用参数设置为通配符类型: 但是,在使用具有泛型参数的类时,如果将该参数的类型设置为泛型,则无法将该类的对象分配给相同类型/泛型的类型,后者(内部/嵌套)参数是通配符类型: 具体的编译错误是: 凭