Как найти тип объекта в Go?

387

Как мне найти тип объекта в Go? В Python я просто использую, typeofчтобы выбрать тип объекта. Аналогично в Go, есть ли способ реализовать то же самое?

Вот контейнер, из которого я итерирую:

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

Я не могу получить тип строк объекта в этом случае, который является массивом строк.

Рахул
источник
Стандартная ссылка не работает в моей программе. Я должен был включить исходный код мой плохой.
Рахул
6
fmt.Printf("%T\n", var)
Мех

Ответы:

470

В пакете отражения Go есть методы для проверки типа переменных.

Следующий фрагмент выведет тип отражения строки, целого числа и числа с плавающей точкой.

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

}

Вывод:

Hello, playground
string
int
float64

см. http://play.golang.org/p/XQMcUVsOja, чтобы увидеть его в действии.

Дополнительная документация здесь: http://golang.org/pkg/reflect/#Type

dethtron5000
источник
отразить не работает для меня. Я обновил вопрос. Я включил фрагмент кода в этом случае.
Рахул
462

Я нашел 3 способа вернуть тип переменной во время выполнения:

Использование форматирования строки

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

Используя отражать пакет

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

Использование утверждений типа

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

Каждый метод имеет свой лучший вариант использования:

  • форматирование строки - короткая и низкая занимаемая площадь (нет необходимости импортировать отражающий пакет)

  • отражать пакет - когда нужно больше подробностей о типе, у нас есть доступ к полным возможностям отражения

  • утверждения типа - позволяет группировать типы, например, распознавать все типы int32, int64, uint32, uint64 как «int»

Grzegorz Luczywo
источник
3
Кажется, что вы можете избавиться от переменной t, так t := v.(type)становится v.(type)и _ = tбольше не нужно.
Akavall
3
На основе теста усеченных, отраженный подход является удивительно более эффективным gist.github.com/mrap/7f08c9549289b6aea2923c27888e7e3e
Майк Rapadas
case 'T': p.fmt.fmtS(reflect.TypeOf(arg).String()), Пакет fmt использует тип отражения для печати
Fantasy_RQG
50

Используйте пакет отражения :

Пакет отражения реализует отражение во время выполнения, позволяя программе манипулировать объектами произвольных типов. Типичное использование состоит в том, чтобы получить значение с интерфейсом статического типа {} и извлечь информацию о его динамическом типе, вызвав TypeOf, который возвращает тип.

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

Производит:

bool
string
int
float64
[]string

Игровая площадка

Пример использования 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
}

Производит:

bool
string
int
float64
string

Игровая площадка

Intermernet
источник
отражать только отображает стандартные типы. Я не могу получить типы элементов контейнера списка.
Рахул
Я обновил свой ответ, чтобы включить часть строк. Reflect работает для любого типа. Пожалуйста, прочитайте документы: golang.org/pkg/reflect & blog.golang.org/laws-of-reflection должно быть достаточно, хотя есть много вопросов SO, связанных с рефлексией в Go, которые также должны помочь вам.
Интермернет
2
тьфу, как я могу определить, является ли тип строкой? if reflect.TypeOf(err) == string?
Александр Миллс
43

Чтобы получить строковое представление:

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

% T Go-синтаксическое представление типа значения

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

Выходы:

string
int
float64
bool
globby
источник
очень прагматичный подход +1
Биджан
16

Я бы держался подальше от отражения. пакет. Вместо этого используйте% 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

Лучший способ - использовать концепцию отражения в Google.
reflect.TypeOfдает тип вместе с именем пакета
reflect.TypeOf().Kind()дает подчеркивание типа

Джитен
источник
1
Я думаю, что это лучший ответ
Эцио
9

Чтобы быть кратким, пожалуйста, используйте fmt.Printf("%T", var1) или другие варианты в пакете fmt.

пр-собутыльник
источник
4

Вы можете проверить тип любой переменной / экземпляра во время выполнения либо с помощью функции «отражать» пакетов, TypeOfлибо с помощью 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

Чтобы получить тип полей в структуре

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

Вывод

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

Смотрите в IDE https://play.golang.org/p/bwIpYnBQiE

неги йоги
источник
0

Вы можете использовать reflect.TypeOf.

  • Основной тип (например: int, string): он возвращает его имя (например: int, string)
  • STRUCT: он будет возвращать что - то в формате <package name>.<struct name>(например: main.test)
夜阑 听风
источник
0

Если у нас есть эти переменные:

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

1: fmt.Printf% T format: чтобы использовать эту функцию, вы должны импортировать «fmt»

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

2: функция отражения. Тип : для использования этой функции необходимо импортировать «отражение».

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

3: refle.ValueOf (X) .Kind () : чтобы использовать эту функцию, вы должны импортировать «отражения»

fmt.Println(reflect.ValueOf(counter).Kind()) // counter type:  int
Хамед Наимаи
источник
0

Вы можете использовать: interface{}..(type)как на этой детской площадке

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)
      }
    }
}
Хасан Юсеф
источник