2016-08-26 3 views
3

Ich habe dieses structs:"instanceof" gleichwertig in Golang

type Event interface { 
    Accept(EventVisitor) 
} 

type Like struct { 
} 

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

Wie kann ich testen, dass event eine Like Instanz?

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

ich:

Typ Wie ist kein Ausdruck event Event

Antwort

16

Sie könnten werfen es einfach und sehen, ob es nicht:

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

Ist Gibt es eine Möglichkeit, dies zu abstrahieren? Ist es möglich den "type" Like als Funktionsparameter zu übergeben? Ich würde es gerne mit mehreren Typen testen, wenn mehrere Int-Eingaben vorliegen. –

+0

@bigdestroyer gibt es einen Grund, warum Sie dies auf diese Weise tun möchten? Nicht zu sagen, dass Typprüfung nicht ihren Platz hat, aber es scheint nicht, was Sie hier wirklich tun wollen. Es sieht so aus, als ob Sie ein nicht exportiertes Attribut in der Struktur haben möchten, das den Typ angibt, der in der Schnittstelle einen Getter hat. –

+0

Nun, ich möchte testen, dass ab dem Wert 0 eine Instanz von "Like" erstellt wird; Ab dem Wert 1 wird eine Instanz von 'Following' erstellt und so weiter. Jeder ist ein anderer Typ, der eine 'Event'-Schnittstelle implementiert. Ich möchte kein Feld, das den Typ angibt, sondern nur die "Factory" -Funktion testen. Was denken Sie? Du hast meine ursprüngliche Frage gelöst, also akzeptiere ich BTW. –

3

die TypeOf() Methode gibt ein Objekt vom Typ Type zurück und Sie erhalten t er Name dieses Typs als eine Zeichenfolge mit der Name() Methode.

ich nicht getestet haben, aber so etwas wie dies funktionieren kann:

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

Danke für Ihre Antwort. Gibt es eine Möglichkeit, den Namen ("Like") vom Typ Like zu erhalten? Ich meine, ohne Hardcoding ... –

+1

Ich denke, es ist einfacher, [type assertions] (https://golang.org/ref/spec#Type_assertions) wie in @ dave's Antwort zu verwenden. –

1

Späte Antwort, aber das funktioniert gut

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 
} 

Spielplatz (online ausführen): https://play.golang.org/p/tcQqdzUGMlL

+0

Wenn Sie eine Schnittstelle mit einem Basistyp wie float32 vergleichen möchten, können Sie 'if reflect.TypeOf (objectPtr) .Kind() == reflect.Float32 {}' verwenden. Ein Beispiel: https://stackoverflow.com/a/49206944/4206925 – MewX