当前位置: 首页 > 面试题库 >

满足接口的Go结构方法的类型

呼延卓
2023-03-14
问题内容

给出以下Go代码示例:

package main

import "fmt"

type greeter interface {
    hello()
    goodbye()
}

type tourGuide struct {
    name string
}

func (t tourGuide) hello() {
    fmt.Println("Hello", t.name)
}

func (t *tourGuide) goodbye() {
    fmt.Println("Goodbye", t.name)
}

func main() {
    var t1 tourGuide = tourGuide{"James"}
    t1.hello()   // Hello James
    t1.goodbye() // Goodbye James (same as (&t1).goodbye())

    var t2 *tourGuide = &tourGuide{"Smith"}
    t2.hello()   // Hello Smith
    t2.goodbye() // Goodbye Smith (same as (*t2).hello())

    // illegal: t1 is not assignable to g1 (why?)
    // var g1 greeter = t1

    var g2 greeter = t2
    g2.hello()   // Hello Smith
    g2.goodbye() // Goodbye Smith
}

我可以tourGuide使用tourGuide类型的变量t1或指向tourGuide的指针来调用结构的两个方法t2。换句话说,我可以T使用类型为T或的变量来使用Receiver
调用方法*T。类似地,我可以调用一个方法*T使用类型的变量接收机T(如果T是可寻址的)或*T。我了解编译器会在此处处理这些差异(请参见代码中的注释)。

但是,当我们实现接口时,情况会发生变化。在上面的代码中,类型为greeterinterface
的变量可以从指针分配,tourGuide但不能从指针分配tourGuide

谁能告诉我为什么会这样吗?为什么我可以打电话t1.hello()t1.goodbye()t1对于接口来说却是不足够的greeter


问题答案:

如果方法具有指针接收器,则只能将指针值用作接收器值。因此,要在某个值上调用此方法,该值本身必须是一个指针,或者必须有可能获取其地址(用作接收方)。

例如,如果您有一个变量,则该变量是可寻址的,因此可以获取其地址并将其用作接收器。规范允许您执行此操作,这会自动发生。

包装在接口中的值是不可寻址的。创建接口值时,将复制包装在接口中的值。因此,无法使用其地址。从理论上讲,您可以允许获取副本的地址,但这将带来(甚至)比提供的好处更多的混乱,因为该地址将指向副本,并且带有指针接收器的方法只能修改副本而不是原始的。



 类似资料:
  • 问题内容: 假设我们了解到, 用于类型明确的方法定义,GO编译器隐式定义了相同的方法类型和 反之亦然 ,如果我声明, 并宣布 然后GO编译器给出错误, 这表明,指针方法是隐式定义的, 反之亦然 在下面的代码中, GO编译器出现错误, 在,因为隐式指针方法满足接口,但是隐式非指针方法不满足。 题: 为什么隐式非指针方法不满足接口? 问题答案: 让我们看一下语言规范: 类型可能具有与之关联的 方法集

  • 问题内容: 目前我有这样的事情 main.go 还有我的工作包 和 我正在传递给NewJob的函数是在goroutine上每2秒执行一次,但是我想访问我传递的匿名结构…但是当我尝试访问时 编号 我越来越 t.Id未定义(类型interface {}是没有方法的接口) 但是打印t给我预期的结果 {1} 问题答案: 您必须先将其声明为兼容类型,然后才能访问其字段。

  • 本文向大家介绍Go语言中的方法、接口和嵌入类型详解,包括了Go语言中的方法、接口和嵌入类型详解的使用技巧和注意事项,需要的朋友参考一下 概述 在 Go 语言中,如果一个结构体和一个嵌入字段同时实现了相同的接口会发生什么呢?我们猜一下,可能有两个问题: 1.编译器会因为我们同时有两个接口实现而报错吗? 2.如果编译器接受这样的定义,那么当接口调用时编译器要怎么确定该使用哪个实现? 在写了一些测试代码

  • 问题内容: 我将如何为正在实现接口的内部类编写构造函数?我知道我可以上一门全新的课,但是我认为必须有一种方法可以做到这一点: 当我输入此内容时,它不会将AbstractAction方法识别为构造函数(编译器要求返回类型)。有人有主意吗? 问题答案: 只需在扩展类的名称后面插入参数即可: 另外,您可以使用初始化块:

  • 问题内容: 我的包中有一个结构,上面有耗时的方法,通过工厂函数进行构造也很耗时。因此,在依赖于该其他结构的包中,我希望能够在创建后使用伪造的工厂函数和伪造的结构对其进行测试。由于结构是通过工厂函数构造的,因此我想伪造工厂函数,并在测试期间将替代工厂函数传递给我的结构。 昂贵的包装的一个例子是: 我的主包装使用以下代码: 但是,此代码抱怨以下错误: 。\ main.go:6:不能在字段值中使用昂贵的

  • 在项目中,我定义了平行的文件夹service和dao,如何将dao层的结构体作为service层方法的接收者?