Como encontrar o tipo de um objeto no Go?

387

Como encontro o tipo de um objeto no Go? No Python, eu apenas uso typeofpara buscar o tipo de objeto. Da mesma forma, no Go, existe uma maneira de implementar o mesmo?

Aqui está o contêiner do qual estou iterando:

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

Eu não sou capaz de obter o tipo de linhas de objeto neste caso, que é uma matriz de seqüências de caracteres.

Rahul
fonte
A referência padrão não está funcionando no meu programa. Eu deveria ter incluído o código fonte do meu mal.
Rahul
6
fmt.Printf("%T\n", var)
meh

Respostas:

470

O pacote de reflexão Go possui métodos para inspecionar o tipo de variáveis.

O trecho a seguir imprimirá o tipo de reflexão de uma sequência, número inteiro e número flutuante.

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

}

Resultado:

Hello, playground
string
int
float64

veja: http://play.golang.org/p/XQMcUVsOja para visualizá-lo em ação.

Mais documentação aqui: http://golang.org/pkg/reflect/#Type

dethtron5000
fonte
refletir não está funcionando para mim. Eu atualizei a pergunta. Eu incluí um trecho de código nesse caso.
Rahul
462

Eu encontrei 3 maneiras de retornar o tipo de uma variável em tempo de execução:

Usando formatação de string

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

Usando refletir pacote

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

Usando asserções de tipo

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

Todo método tem um melhor caso de uso diferente:

  • formatação de string - pegada curta e baixa (não é necessário importar o pacote refletido)

  • pacote refletir - quando precisarmos de mais detalhes sobre o tipo, teremos acesso aos recursos completos de reflexão

  • asserções de tipo - permite agrupar tipos, por exemplo, reconhecer todos os tipos int32, int64, uint32, uint64 como "int"

Grzegorz Luczywo
fonte
3
Parece que você pode se livrar da variável t, então t := v.(type)se torna v.(type)e _ = tnão é mais necessária.
Akavall 28/02
3
Com base em uma referência barebones, a reflectir a abordagem é surpreendentemente mais eficiente gist.github.com/mrap/7f08c9549289b6aea2923c27888e7e3e
Mike Rapadas
case 'T': p.fmt.fmtS(reflect.TypeOf(arg).String()). pacote fmt usando refletir para imprimir o tipo
Fantasy_RQG
50

Use o pacote de reflexão :

O pacote refletir implementa a reflexão em tempo de execução, permitindo que um programa manipule objetos com tipos arbitrários. O uso típico é pegar um valor com a interface de tipo estático {} e extrair suas informações de tipo dinâmico chamando TypeOf, que retorna um 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))
}

Produz:

bool
string
int
float64
[]string

Parque infantil

Exemplo usando 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
}

Produz:

bool
string
int
float64
string

Parque infantil

Intermernet
fonte
reflect apenas exibe os tipos padrão. Não consigo obter tipos de elementos de um contêiner de lista.
Rahul
Atualizei minha resposta para incluir uma fatia de strings. Reflect funciona para qualquer tipo. Leia os documentos: golang.org/pkg/reflect & blog.golang.org/laws-of-reflection devem ser suficientes, embora existam muitas perguntas relacionadas à reflexão no Go que possam ajudá-lo.
Intermernet
2
ughhh, como posso determinar se o tipo é uma string? if reflect.TypeOf(err) == string?
Alexander Mills
43

Para obter uma representação de string:

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

% T uma representação de sintaxe Go do tipo de valor

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

Saídas:

string
int
float64
bool
globby
fonte
abordagem muito pragmática +1
Bijan
16

Eu ficaria longe da reflexão. pacote. Em vez disso, use% 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
fonte
13

A melhor maneira é usar o conceito de reflexão no Google.
reflect.TypeOfdá tipo junto com o nome do pacote
reflect.TypeOf().Kind()dá tipo sublinhado

Jiten
fonte
11
Isso eu acho que é uma resposta melhor
Ezio
9

Para ser breve, use fmt.Printf("%T", var1) ou suas outras variantes no pacote fmt.

pr-pal
fonte
4

Você pode verificar o tipo de qualquer variável / instância em tempo de execução, usando a TypeOffunção de pacotes "reflect" ou usando 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
fonte
4

Para obter o tipo de campos em 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())
   }
}

Resultado

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

Veja no IDE https://play.golang.org/p/bwIpYnBQiE

negi Yogi
fonte
0

você pode usar reflect.TypeOf.

  • tipo básico (por exemplo: int, string): ele irá retornar o seu nome (por exemplo: int, string)
  • struct: retornará algo no formato <package name>.<struct name>(por exemplo main.test:)
夜阑 听风
fonte
0

Se tivermos essas variáveis:

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

1: formato fmt.Printf% T : para usar esse recurso, você deve importar "fmt"

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

2: função reflect.TypeOf : para usar este recurso, você deve importar "reflect"

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

3: reflect.ValueOf (X) .Kind () : para usar este recurso, você deve importar "reflect"

fmt.Println(reflect.ValueOf(counter).Kind()) // counter type:  int
Hamed Naeemaei
fonte
0

Você pode usar: interface{}..(type)como neste playground

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
fonte