Создание объектов динамически на основе строки - PullRequest
0 голосов
/ 22 октября 2018

Я пытаюсь динамически создавать структуры на основе строки.

В приведенном ниже примере отражение. Типы & c и & c1 отличаются, потому что я возвращаю интерфейс {} из makeInstance.TypeOf c и c1 одинаковы.

Мой вопрос: как мне изменить способ обработки вывода makeInstance, чтобы он создавал объект, идентичный c1, но все равно позволял бы мне создавать объекты, идентичные b1?

type Car struct {
    Make  int `json:"make"`
    Model int `json:"model"`
}

type Bus struct {
    Seats int `json:"seats"`
    Route int `json:"route"`
}

var typeRegistry = make(map[string]reflect.Type)

func init() {
    typeRegistry["Car"] = reflect.TypeOf(Car{})
    typeRegistry["Bus"] = reflect.TypeOf(Bus{})

}

func makeInstance(name string) interface{} {
    v := reflect.New(typeRegistry[name]).Elem()

    return v.Interface()
}

func main() {

    c := makeInstance("Car")
    b := makeInstance("Bus")

    var b1 Bus
    var c1 Car

    fmt.Println(reflect.TypeOf(&c))
    fmt.Println(reflect.TypeOf(&c1))
    fmt.Println(reflect.TypeOf(c))  
    fmt.Println(reflect.TypeOf(c1))

Редактировать:

Мой общий результат - иметь программу, которая читает конфигурационный файл json, в котором будут перечислены типы объектов, которые я хочу отключить, и нажму на остальные API и соберу, например,

{
    "auth":[{
                "username": "admin",
                "password": "admin"
            }],
    "transport":[
            {
                "vehicle":["car", "bus"]
            }]
}

При прохождении через автомобиль он попадет в API, выполнит запрос и вернет данные.Затем я хотел бы создать массив всех транспортных средств, включенных в конфигурацию, и разархивировать в него ответ json.Я пытаюсь создавать объекты динамически, чтобы избежать проверки, если автомобиль = автомобиль, автомобиль = автобус и т. Д., Так как в конечном итоге у меня будет много типов транспортных средств, но может не всегда иметь все транспортные средства, и это кажется длинным.

Ответы [ 2 ]

0 голосов
/ 22 октября 2018

Вы, вероятно, должны остановиться и прочитать об утверждениях типа значений интерфейса.Go - это , а не язык с динамической типизацией, и то, что вы пытаетесь сделать, с большой вероятностью потерпит неудачу:

Пока вы работаете с interface{}, вы просто не можете получить доступ к полям (Марка, Модель, Места, Маршрут, ...) без отражения.Если вы хотите написать x.Make, вы должны иметь x типа Car или *Car (а не интерфейс {}).

Чтобы получить из cтипа interface{}, например, Car you must type assert:

var car Car = c.(Car)

Обратите внимание, что вы не можете делать динамические утверждения типа (без отражения) и что c.(Car) завершится ошибкойесли c содержит, например, Bus.Таким образом, после json.Unmarshaling в универсальный интерфейс {} вам придется включить известный тип и утверждать этот тип.Это означает, что вы все равно напишите специальный код для каждого типа.

0 голосов
/ 22 октября 2018

Функция возвращает значения типа Car и Bus как написано.Если вы хотите, чтобы переменная в main имела определенный тип, то используйте утверждение типа:

c := makeInstance("Car").(Car)

Если ваша цель - получить указатель на значения этих типов, тогда верните указатель из makeInstance:

func makeInstance(name string) interface{} {
    return reflect.New(typeRegistry[name]).Interface()
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...