Jak znaleźć typ obiektu w Go?

387

Jak znaleźć typ obiektu w Go? W Pythonie po prostu używam typeofdo pobierania typu obiektu. Podobnie w Go, czy istnieje sposób na wdrożenie tego samego?

Oto kontener, z którego iteruję:

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

W tym przypadku nie jestem w stanie uzyskać typu linii obiektu, która jest tablicą ciągów.

Rahul
źródło
Standardowy plik referencyjny nie działa w moim programie. Powinienem był dołączyć mój kod źródłowy.
Rahul
5
fmt.Printf("%T\n", var)
Meh

Odpowiedzi:

470

Pakiet refleksyjny Go zawiera metody sprawdzania typu zmiennych.

Poniższy fragment kodu wypisze typ odbicia ciągu, liczby całkowitej i liczby zmiennoprzecinkowej.

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))

}

Wynik:

Hello, playground
string
int
float64

patrz: http://play.golang.org/p/XQMcUVsOja, aby zobaczyć to w akcji.

Więcej dokumentacji tutaj: http://golang.org/pkg/reflect/#Type

dethtron5000
źródło
odzwierciedlają, że nie działa dla mnie. Zaktualizowałem pytanie. W tym przypadku zawarłem fragment kodu.
Rahul
462

Znalazłem 3 sposoby zwracania typu zmiennej w czasie wykonywania:

Korzystanie z formatowania ciągów

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

Korzystanie z pakietu odzwierciedlającego

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

Korzystanie z asercji typu

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

Każda metoda ma inny najlepszy przypadek użycia:

  • formatowanie łańcucha - krótki i niski ślad (nie jest konieczne importowanie pakietu odbijającego)

  • pakiet odblaskowy - gdy potrzebujesz więcej informacji o typie, mamy dostęp do pełnych możliwości odbicia

  • asercje typów - pozwala grupować typy, na przykład rozpoznaje wszystkie typy int32, int64, uint32, uint64 jako „int”

Grzegorz Luczywo
źródło
3
Wygląda na to, że możesz pozbyć się zmiennej t, więc t := v.(type)staje się v.(type)i _ = tnie jest już potrzebna.
Akavall
3
Oparte na benchmarku barebone podejście refleksyjne jest zaskakująco wydajne gist.github.com/mrap/7f08c9549289b6aea2923c27888e7e3e
Mike Rapadas
case 'T': p.fmt.fmtS(reflect.TypeOf(arg).String()). pakiet fmt z wykorzystaniem typu odbicia do wydruku
Fantasy_RQG
50

Użyj pakietu odzwierciedlającego :

Pakiet odzwierciedla implementuje odbicie w czasie wykonywania, umożliwiając programowi manipulowanie obiektami o dowolnych typach. Typowym zastosowaniem jest pobranie wartości za pomocą interfejsu typu statycznego {} i wyodrębnienie jej informacji o typie dynamicznym poprzez wywołanie TypeOf, która zwraca Type.

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))
}

Produkuje:

bool
string
int
float64
[]string

Plac zabaw

Przykład użycia 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
}

Produkuje:

bool
string
int
float64
string

Plac zabaw

Internet
źródło
odzwierciedla tylko wyświetla standardowe typy. Nie jestem w stanie uzyskać typów elementów kontenera listy.
Rahul
Zaktualizowałem swoją odpowiedź, aby zawierała kawałek ciągów. Reflect działa na każdym typie. Przeczytaj dokumenty: golang.org/pkg/reflect & blog.golang.org/laws-of-reflection powinny wystarczyć, chociaż istnieje wiele SO pytań związanych z refleksją w Go, które również powinny ci pomóc.
Intermernet
2
ughh, jak mogę ustalić, czy typ jest łańcuchem? if reflect.TypeOf(err) == string?
Alexander Mills,
43

Aby uzyskać ciąg znaków:

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

% T reprezentacja składni Go typu wartości

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

Wyjścia:

string
int
float64
bool
globby
źródło
bardzo pragmatyczne podejście +1
Bijan
16

Trzymałbym się z dala od odbicia. pakiet. Zamiast tego użyj% 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)
 }
Harold Ramos
źródło
13

Najlepszym sposobem jest użycie koncepcji refleksji w Google.
reflect.TypeOfpodaje typ wraz z nazwą pakietu
reflect.TypeOf().Kind()podaje typ podkreślenia

Jiten
źródło
1
Myślę, że to lepsza odpowiedź
Ezio
9

Krótko mówiąc, użyj fmt.Printf("%T", var1) lub jego innych wariantów w pakiecie fmt.

pr-pal
źródło
4

Możesz sprawdzić typ dowolnej zmiennej / instancji w środowisku wykonawczym, używając TypeOffunkcji pakietów „reflect” lub 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)
}
Kabeer Shaikh
źródło
4

Aby uzyskać typ pól w struct

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())
   }
}

Wynik

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

Zobacz w IDE https://play.golang.org/p/bwIpYnBQiE

negi jogin
źródło
0

możesz użyć reflect.TypeOf.

  • typ podstawowy (np int, string) zwróci swoją nazwę (np int, string)
  • struct: zwróci coś w formacie <package name>.<struct name>(np . main.test:)
夜阑 听风
źródło
0

Jeśli mamy te zmienne:

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

1: format fmt.Printf% T : aby skorzystać z tej funkcji, należy zaimportować plik „fmt”

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

2: funkcja reflect.TypeOf : aby skorzystać z tej funkcji, należy zaimportować „reflect”

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

3: reflect.ValueOf (X) .Kind () : aby skorzystać z tej funkcji, należy zaimportować „reflect”

fmt.Println(reflect.ValueOf(counter).Kind()) // counter type:  int
Hamed Naeemaei
źródło
0

Możesz użyć: interface{}..(type)jak na tym placu zabaw

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)
      }
    }
}
Hasan A Yousef
źródło