Обратное отражение. ТипOf - PullRequest
0 голосов
/ 05 мая 2019

Я хочу получить тип значения, которое я сохранил один раз.Я использовал отражатель. Тип () и сохранил тип.затем попробуйте использовать тип переключателя.тип всегда будет "* refle.rtype".Я не смог получить ни одно утверждение по типу.

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var alltypes []interface{}

    alltypes = append(alltypes, reflect.TypeOf(true))
    alltypes = append(alltypes, reflect.TypeOf(0.0))
    alltypes = append(alltypes, reflect.TypeOf(0))
    fmt.Printf("%T\t%q\n", alltypes, alltypes)

    for _, v := range alltypes {
        fmt.Printf("%T\t%q\n", v, v)
        res, ok := v.(bool)
        fmt.Println("res: ", res, " ok: ", ok)
        switch v.(type) {
        default:
            fmt.Printf("unexpected type %T\n", v)
        case bool:
            fmt.Println("bool type!")
        case int:
            fmt.Println("int type!")
        case float64:
            fmt.Println("float64 type!")
        }
    }

}

Детская площадка: https://play.golang.org/p/kqDo4DPYjra

Ответы [ 2 ]

2 голосов
/ 05 мая 2019

A reflect.Type не содержит значения, которое вы могли бы напечатать (на самом деле вы могли бы, но это могло быть только reflect.Type, а не то, что вы хотите). reflect.Type - это просто дескриптор типа (который вы получили из значения).

Однако вы можете создать значение типа, представленного reflect.Type, и вы можете ввести значения из тех значений, которые вы изначально хотели.

Чтобы создать новое значение указателя, используйте reflect.New(). Чтобы получить указанное значение, используйте Value.Elem(). Все они обернуты в reflect.Value. Чтобы развернуть его, используйте Value.Interface().

Например:

for _, v := range alltypes {
    fmt.Printf("%T\t%q\n", v, v)
    value := reflect.New(v.(reflect.Type)).Elem().Interface()
    switch value.(type) {
    default:
        fmt.Printf("unexpected type %T\n", v)
    case bool:
        fmt.Println("bool type!")
    case int:
        fmt.Println("int type!")
    case float64:
        fmt.Println("float64 type!")
    }
}

Будет выведено (попробуйте на Go Playground ):

[]interface {}  ["bool" "float64" "int"]
*reflect.rtype  "bool"
bool type!
*reflect.rtype  "float64"
float64 type!
*reflect.rtype  "int"
int type!

Также, если вы не хотите создавать новые значения, просто протестируйте тип, «сохраните» дескрипторы reflect.Type интересующих вас типов и используйте обычный switch для типа:

var (
    TypeBool    = reflect.TypeOf(true)
    TypeFloat64 = reflect.TypeOf(0.0)
    TypeInt     = reflect.TypeOf(0)
)

func main() {
    var alltypes []interface{}

    alltypes = append(alltypes, reflect.TypeOf(true))
    alltypes = append(alltypes, reflect.TypeOf(0.0))
    alltypes = append(alltypes, reflect.TypeOf(0))
    fmt.Printf("%T\t%q\n", alltypes, alltypes)

    for _, v := range alltypes {
        fmt.Printf("%T\t%q\n", v, v)
        switch v {
        default:
            fmt.Printf("unexpected type %T\n", v)
        case TypeBool:
            fmt.Println("bool type!")
        case TypeInt:
            fmt.Println("int type!")
        case TypeFloat64:
            fmt.Println("float64 type!")
        }
    }
}

Будет выведено (попробуйте на Go Playground ):

[]interface {}  ["bool" "float64" "int"]
*reflect.rtype  "bool"
bool type!
*reflect.rtype  "float64"
float64 type!
*reflect.rtype  "int"
int type!

Рекомендуемое чтение: The Go Blog: Законы отражения

1 голос
/ 05 мая 2019

В зависимости от того, что вы хотите сделать, вам не обязательно делать это с утверждением типа.v.(reflect.Type).Kind() скажет вам, что это за тип (например, reflect.Bool, reflect.Float64, reflect.Int и т. Д.).

...