栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 面试经验 > 面试问答

不能在分配中使用MockDaoInterface文字(类型为MockDaoInterface)作为类型s3.DaoInterface:MockDaoInterface不实现s3.DaoInterfac

面试问答 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

不能在分配中使用MockDaoInterface文字(类型为MockDaoInterface)作为类型s3.DaoInterface:MockDaoInterface不实现s3.DaoInterfac

当您尝试将 具体 类型分配或传递(或转换)为接口类型时,会出现此编译时错误。并且类型本身不实现接口,仅实现 指向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 Stringers = 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 = &mfmt.Println(s)

我们得到了预期的结果(在Go Playground上尝试):

something

因此,获取此编译时错误的要求:

  • 分配(或传递或转换)的 非指针 具体类型的值
  • 分配给(或传递给或转换为)的接口类型
  • 具体类型具有接口的必需方法,但带有 指针接收器

解决此问题的可能性:

  • 必须使用指向该值的指针,该指针的方法集将包括带有指针接收器的方法
  • 否则必须将接收者类型更改 为非指针 ,因此非指针具体类型的方法集也将包含方法(并因此满足接口)。这可能是可行的,也可能是不可行的,就像该方法必须修改该值一样,非指针接收器也不是一种选择。

结构和嵌入

使用结构和嵌入时,实现接口的通常不是“您”(提供方法实现),而是嵌入到中的类型

struct
。像这个例子一样:

type MyType2 struct {    MyType}m := MyType{value: "something"}m2 := MyType2{MyType: m}var s Stringers = m2 // Compile-time error again

再次出现编译时错误,因为的方法集

MyType2
不包含
String()
Embedded
MyType
的方法,仅包含的方法集
*MyType2
,因此以下工作(在GoPlayground上尝试):

var s Stringers = &m2

如果我们

*MyType
仅嵌入并使用 非指针 ,也可以使其工作
MyType2
(在GoPlayground上尝试):

type MyType2 struct {    *MyType}m := MyType{value: "something"}m2 := MyType2{MyType: &m}var s Stringers = m2

另外,无论我们嵌入什么(

MyType
*MyType
),如果我们使用指针
*MyType2
,它将始终有效(在Go
Playground
上尝试):

type MyType2 struct {    *MyType}m := MyType{value: "something"}m2 := MyType2{MyType: &m}var s Stringers = &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{} = mfmt.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))


转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/417765.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号