【问题标题】:"instanceof" equivalent in GolangGolang 中的“instanceof”等价物
【发布时间】:2022-05-11 15:54:41
【问题描述】:

我有这些结构:

type Event interface {
    Accept(EventVisitor)
}

type Like struct {
}

func (l *Like) Accept(visitor EventVisitor) {
    visitor.visitLike(l)
}

如何测试eventLike 实例?

func TestEventCreation(t *testing.T) {
    event, err := New(0)
    if err != nil {
        t.Error(err)
    }
    if reflect.TypeOf(event) != Like {
        t.Error("Assertion error")
    }
}

我明白了:

Type Like 不是表达式事件 Event

【问题讨论】:

    标签: go


    【解决方案1】:

    你可以做一个类型断言,看看它是否失败:

    event, err := New(0)
    if err != nil {
        t.Error(err)
    }
    _, ok := event.(Like)
    if !ok {
        t.Error("Assertion error")
    }
    

    【讨论】:

    • 有没有办法抽象这个?是否可以将“类型”作为函数参数传递?给定几个 int 输入,我想用几种类型对其进行测试。
    • @bigdestroyer 你有理由这样做吗?并不是说类型检查没有它的位置,但它似乎并不是你真正想要在这里做的。似乎您想要做的是在结构上有一个未导出的属性,该属性指示其在接口中具有关联的 Getter 的类型。
    • 好吧,我想测试一下,从值 0 开始,会创建一个 Like 的实例;从值 1 开始,创建 Following 的实例,依此类推。每个都是实现Event 接口的不同类型。我不想要任何指示其类型的字段,只需测试“工厂”功能。你怎么看?你解决了我最初的问题,所以我接受 BTW。
    【解决方案2】:

    TypeOf() 方法返回一个Type 类型的对象,您可以使用Name() 方法以字符串形式获取该类型的名称。

    我尚未对此进行测试,但类似的方法可能有效:

    if reflect.TypeOf(event).Name() != "Like" {
    

    【讨论】:

    • 感谢您的回答。有没有办法从 Like 类型中获取名称(“Like”)?我的意思是,没有硬编码...
    • 我认为在@dave 的回答中使用type assertions 更简单。
    【解决方案3】:

    迟到的答案,但这很好用

    package main
    
    import (
      "fmt"
      "reflect"
    )
    
    type SomeStruct1 struct{}
    type SomeStruct2 struct{}
    
    func IsInstanceOf(objectPtr, typePtr interface{}) bool {
      return reflect.TypeOf(objectPtr) == reflect.TypeOf(typePtr)
    }
    
    func main() {
      //sample variables
      someString := "Some String"
      someFloat := float32(2.4)
      someStruct1 := SomeStruct1{}
      someStruct2 := SomeStruct2{}
      someStruct1Ptr := &SomeStruct1{}
    
      // primitive string
      fmt.Println("string <-> *string \t\t", IsInstanceOf(someString, (*string)(nil)))   //false
      fmt.Println("*string <-> *string \t\t", IsInstanceOf(&someString, (*string)(nil))) //true
    
      // primitive float32
      fmt.Println("float32 <-> *float32 \t\t", IsInstanceOf(someFloat, (*float32)(nil)))   //false
      fmt.Println("*float32 <-> *float32 \t\t", IsInstanceOf(&someFloat, (*float32)(nil))) //true
    
      // structure
      fmt.Println("SomeStruct1 <-> *SomeStruct1 \t", IsInstanceOf(someStruct1, (*SomeStruct1)(nil)))     //false
      fmt.Println("*SomeStruct1 <-> *SomeStruct1 \t", IsInstanceOf(&someStruct1, (*SomeStruct1)(nil)))   //true
      fmt.Println("*SomeStruct2 <-> *SomeStruct1 \t", IsInstanceOf(&someStruct2, (*SomeStruct1)(nil)))   //false
      fmt.Println("*SomeStruct1 <-> *SomeStruct1 \t", IsInstanceOf(someStruct1Ptr, (*SomeStruct1)(nil))) //true
    }
    

    游乐场(在线运行):https://play.golang.org/p/tcQqdzUGMlL

    【讨论】:

    • 如果你想比较一个接口和像 float32 这样的基本类型,你可以使用if reflect.TypeOf(objectPtr).Kind() == reflect.Float32 {}。一个例子:stackoverflow.com/a/49206944/4206925
    【解决方案4】:

    最接近的翻译:

    // java
    if (x instanceof y) {
        // x is a y
    }
    

    是:

    // go
    if _, ok := x.(y); ok {
        // x is a y
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-12-10
      • 1970-01-01
      • 1970-01-01
      • 2015-04-27
      • 2014-07-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多