Wie finde ich den Typ eines Objekts in Go?


387

Wie finde ich den Typ eines Objekts in Go? In Python rufe ich nur typeofden Objekttyp ab. Gibt es in Go eine Möglichkeit, dasselbe zu implementieren?

Hier ist der Container, aus dem ich iteriere:

for e := dlist.Front(); e != nil; e = e.Next() {
    lines := e.Value
    fmt.Printf(reflect.TypeOf(lines))
}

Ich kann in diesem Fall den Typ der Objektzeilen, bei denen es sich um ein Array von Zeichenfolgen handelt, nicht ermitteln.


Die Standardreferenz funktioniert nicht in meinem Programm. Ich hätte den Quellcode meiner schlechten enthalten sollen.
Rahul

5
fmt.Printf("%T\n", var)
meh

Antworten:


470

Das Go-Reflection-Paket enthält Methoden zum Überprüfen des Variablentyps.

Das folgende Snippet druckt den Reflektionstyp einer Zeichenfolge, einer Ganzzahl und eines Gleitkommas aus.

package main

import (
    "fmt"
    "reflect"
)

func main() {

    tst := "string"
    tst2 := 10
    tst3 := 1.2

    fmt.Println(reflect.TypeOf(tst))
    fmt.Println(reflect.TypeOf(tst2))
    fmt.Println(reflect.TypeOf(tst3))

}

Ausgabe:

Hello, playground
string
int
float64

Siehe: http://play.golang.org/p/XQMcUVsOja , um es in Aktion anzuzeigen.

Weitere Dokumentation hier: http://golang.org/pkg/reflect/#Type


Ich denke, ich arbeite nicht für mich. Ich habe die Frage aktualisiert. Ich habe in diesem Fall ein Code-Snippet eingefügt.
Rahul

462

Ich habe drei Möglichkeiten gefunden, um den Typ einer Variablen zur Laufzeit zurückzugeben:

Verwenden der Zeichenfolgenformatierung

func typeof(v interface{}) string {
    return fmt.Sprintf("%T", v)
}

Mit Paket reflektieren

func typeof(v interface{}) string {
    return reflect.TypeOf(v).String()
}

Verwenden von Typzusicherungen

func typeof(v interface{}) string {
    switch v.(type) {
    case int:
        return "int"
    case float64:
        return "float64"
    //... etc
    default:
        return "unknown"
    }
}

Jede Methode hat einen anderen besten Anwendungsfall:

  • Zeichenfolgenformatierung - kurzer und geringer Platzbedarf (zum Importieren des Reflect-Pakets nicht erforderlich)

  • Reflect-Paket - Wenn Sie weitere Details zum Typ benötigen, haben Sie Zugriff auf die vollständigen Reflection-Funktionen

  • Typzusicherungen - Ermöglicht die Gruppierung von Typen, z. B. das Erkennen aller int32-, int64-, uint32- und uint64-Typen als "int".


3
Es scheint, dass Sie Variablen loswerden können t, so t := v.(type)wird v.(type)und _ = twird nicht mehr benötigt.
Akavall

3
Basierend auf einem Barebone-Benchmark ist der Reflect-
Mike Rapadas

case 'T': p.fmt.fmtS(reflect.TypeOf(arg).String()). Fmt-Paket mit
Reflect

50

Verwenden Sie das Reflect- Paket:

Paketreflexion implementiert Laufzeitreflexion, sodass ein Programm Objekte mit beliebigen Typen bearbeiten kann. Die typische Verwendung besteht darin, einen Wert mit der statischen Typschnittstelle {} zu verwenden und seine dynamischen Typinformationen durch Aufrufen von TypeOf zu extrahieren, das einen Typ zurückgibt.

package main

import (
    "fmt"
    "reflect"
)

func main() {
    b := true
    s := ""
    n := 1
    f := 1.0
    a := []string{"foo", "bar", "baz"}

    fmt.Println(reflect.TypeOf(b))
    fmt.Println(reflect.TypeOf(s))
    fmt.Println(reflect.TypeOf(n))
    fmt.Println(reflect.TypeOf(f))
    fmt.Println(reflect.TypeOf(a))
}

Produziert:

bool
string
int
float64
[]string

Spielplatz

Beispiel mit ValueOf(i interface{}).Kind():

package main

import (
    "fmt"
    "reflect"
)

func main() {
    b := true
    s := ""
    n := 1
    f := 1.0
    a := []string{"foo", "bar", "baz"}

    fmt.Println(reflect.ValueOf(b).Kind())
    fmt.Println(reflect.ValueOf(s).Kind())
    fmt.Println(reflect.ValueOf(n).Kind())
    fmt.Println(reflect.ValueOf(f).Kind())
    fmt.Println(reflect.ValueOf(a).Index(0).Kind()) // For slices and strings
}

Produziert:

bool
string
int
float64
string

Spielplatz


Reflect zeigt nur die Standardtypen an. Ich kann keine Elementtypen eines Listencontainers abrufen.
Rahul

Ich habe meine Antwort so aktualisiert, dass sie ein Stück Zeichenfolgen enthält. Reflect funktioniert für jeden Typ. Bitte lesen Sie die Dokumente: golang.org/pkg/reflect & blog.golang.org/laws-of-reflection sollte ausreichen, obwohl es viele SO-Fragen im Zusammenhang mit der Reflexion in Go gibt, die Ihnen ebenfalls helfen sollten.
Intermernet

2
ughhh, wie kann ich feststellen, ob der Typ eine Zeichenfolge ist? if reflect.TypeOf(err) == string?
Alexander Mills

43

So erhalten Sie eine Zeichenfolgendarstellung:

Von http://golang.org/pkg/fmt/

% T eine Go-Syntax-Darstellung des Werttyps

package main
import "fmt"
func main(){
    types := []interface{} {"a",6,6.0,true}
    for _,v := range types{
        fmt.Printf("%T\n",v)
    }
}

Ausgänge:

string
int
float64
bool

sehr pragmatischer Ansatz +1
Bijan

16

Ich würde mich vom Nachdenken fernhalten. Paket. Verwenden Sie stattdessen% T.

package main

import (
    "fmt"
)

func main() {
    b := true
    s := ""
    n := 1
    f := 1.0
    a := []string{"foo", "bar", "baz"}

    fmt.Printf("%T\n", b)
    fmt.Printf("%T\n", s)
    fmt.Printf("%T\n", n)
    fmt.Printf("%T\n", f)
    fmt.Printf("%T\n", a)
 }

13

Am besten verwenden Sie das Reflexionskonzept in Google.
reflect.TypeOfgibt Typ zusammen mit dem Paketnamen
reflect.TypeOf().Kind()gibt unterstrichenen Typ


1
Dies ist meiner Meinung nach eine bessere Antwort
Ezio

9

Um es kurz zu machen, verwenden Sie bitte fmt.Printf("%T", var1) oder seine anderen Varianten im fmt-Paket.


4

Sie können den Typ jeder Variablen / Instanz zur Laufzeit überprüfen, indem Sie entweder die Paketfunktion "Reflect" TypeOfverwenden oder Folgendes verwenden fmt.Printf():

package main

import (
   "fmt"
   "reflect"
)

func main() {
    value1 := "Have a Good Day"
    value2 := 50
    value3 := 50.78

    fmt.Println(reflect.TypeOf(value1 ))
    fmt.Println(reflect.TypeOf(value2))
    fmt.Println(reflect.TypeOf(value3))
    fmt.Printf("%T",value1)
    fmt.Printf("%T",value2)
    fmt.Printf("%T",value3)
}

4

Um die Art der Felder in struct zu erhalten

package main

import (
  "fmt"
  "reflect"
)

type testObject struct {
  Name   string
  Age    int
  Height float64
}

func main() {
   tstObj := testObject{Name: "yog prakash", Age: 24, Height: 5.6}
   val := reflect.ValueOf(&tstObj).Elem()
   typeOfTstObj := val.Type()
   for i := 0; i < val.NumField(); i++ {
       fieldType := val.Field(i)
       fmt.Printf("object field %d key=%s value=%v type=%s \n",
          i, typeOfTstObj.Field(i).Name, fieldType.Interface(),
          fieldType.Type())
   }
}

Ausgabe

object field 0 key=Name value=yog prakash type=string 
object field 1 key=Age value=24 type=int 
object field 2 key=Height value=5.6 type=float64

Siehe in IDE https://play.golang.org/p/bwIpYnBQiE


0

Sie können verwenden reflect.TypeOf.

  • Grundtyp (zB : int, string): Es wird sein Name zurückgegeben (zB : int, string)
  • struct: es ist etwas im Format zurückkehren wird <package name>.<struct name>(zB: main.test)

0

Wenn wir diese Variablen haben:

var counter int = 5
var message string  = "Hello"
var factor float32 = 4.2
var enabled bool = false

1: fmt.Printf% T- Format : Um diese Funktion zu verwenden, sollten Sie "fmt" importieren.

fmt.Printf("%T \n",factor )   // factor type: float32

2: Reflect.TypeOf- Funktion : Um diese Funktion zu verwenden, sollten Sie " Reflect " importieren.

fmt.Println(reflect.TypeOf(enabled)) // enabled type:  bool

3: Reflect.ValueOf (X) .Kind () : Um diese Funktion zu verwenden, sollten Sie " Reflect " importieren.

fmt.Println(reflect.ValueOf(counter).Kind()) // counter type:  int

0

Sie können verwenden: interface{}..(type)wie auf diesem Spielplatz

package main
import "fmt"
func main(){
    types := []interface{} {"a",6,6.0,true}
    for _,v := range types{
        fmt.Printf("%T\n",v)
        switch v.(type) {
        case int:
           fmt.Printf("Twice %v is %v\n", v, v.(int) * 2)
        case string:
           fmt.Printf("%q is %v bytes long\n", v, len(v.(string)))
       default:
          fmt.Printf("I don't know about type %T!\n", v)
      }
    }
}


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.