Как использовать утверждение типа из отражения интерфейса в golang? - PullRequest
0 голосов
/ 30 января 2020

Я пытаюсь использовать утверждение типа в golang. с прямым утверждением проблем нет.

a, ok := i.(MyStruct)

, но когда я использую отражение

b, ok := i.(reflect.TypeOf(i))

, я получаю ошибку. В чем была проблема с этим? и как с этим бороться?

Полный код:

package main

import (
     "fmt"
     "reflect"
)

type MyStruct struct {
    field string
}

func main() {
    var i interface{} = MyStruct{field:"Thanks"}

    a, ok := i.(MyStruct)
    fmt.Println(a, ok)

    t := reflect.TypeOf(i)
    fmt.Println(t)

    b, ok := i.(t)
    fmt.Println(b, ok)
}

Спасибо за ваши ответы.

1 Ответ

2 голосов
/ 30 января 2020

Много вещей, но в основном "это не работает таким образом". Элемент внутри скобок в утверждении типа должен быть тип , то есть именем типа или литералом типа. reflect.TypeOf(i) не один из них, это выражение вызова метода. Поэтому это синтаксическая ошибка. refle.TypeOf не «возвращает тип» (это не совсем то, что вы можете сделать в Go), он возвращает refle.Type , который является обычная go структура, содержащая информацию о типе (т.е. своего рода мета-типе).

Но более фундаментальная причина, по которой он не работает, заключается в том, что он ... Go не может знать тип переменной при объявлении. Либо его тип задается явно в объявлении var, либо он выводится из типа значения инициализации в объявлении var x = value или короткого присвоения x := value. невозможно , поскольку тип неизвестен во время компиляции. Go не позволяет вам написать выражение, которое создает неопределенный тип.

Сама цель утверждения типа состоит в том, чтобы получить значение типа интерфейса (который является своего рода «коробкой», которая может хранить значения нескольких типов (или для interface{}, любого типа) и извлекать значение конкретный c конкретный тип. Значение, созданное утверждением, будет иметь тип, названный утверждением, и никакой другой. (В случае присвоения ,ok, если утверждение не выполнено, переменная будет содержать нулевое значение , но все равно будет иметь правильный тип). Если бы вы могли написать утверждение для типа, который был известен только во время выполнения, все это развалилось бы, поэтому вы не можете написать его - это ошибка.

Короче говоря, вы не можете использовать отражение сделать это. Вы можете использовать отражение, чтобы узнать, что тип i, вы можете узнать имя этого типа, вы можете узнать, что его базовый Вид - это Struct, вы можете перечислить поля структуры и получить значения из их и т. д. c ... все это законное использование рефлексии. Но он не может вернуть вам переменную типа MyStruct - способ сделать это - i.(MyStruct).

...