Как динамически регистрировать тип в go lang

#go #struct #dynamic #types #routes

#Вперед #struct #динамический #типы #маршруты

Вопрос:

Я новичок в go, на самом деле я хочу создать API с go, у которого есть динамический маршрут, как я сделал с Lumen, поэтому основная функция примерно такая :

 func main() {
    posts = append(posts, Post{ID: "1", Title: "My first post", Body: "This is the content of my first post"})
    posts = append(posts, Post{ID: "2", Title: "My second post", Body: "This is the content of my second post"})

    db, err = gorm.Open(dbclass.DbDriver, dbclass.DataSourceName)
    if err != nil {
        log.Println("Connection Failed to Open")
    } else {
        log.Println("Connection Established")
    }

    router := mux.NewRouter()
    router.HandleFunc("/{model}", getAll).Methods("GET")
    router.HandleFunc("/{model}", create).Methods("POST")
    router.HandleFunc("/{model}/{id}", getById).Methods("GET")
    router.HandleFunc("/{model}/{id}", update).Methods("PUT")
    router.HandleFunc("/{model}/{id}", delete).Methods("DELETE")

    http.ListenAndServe(":8000", router)
}
  

и я сохраняю файл модели mcustm.go в папке Models.

Поэтому, когда мы хотим получить всю любую модель, мы просто вызываем (пример в postman) что-то вроде этого :

localhost:8000/mcustm

это вызовет функцию GetAll, затем передаст mcustm параметр в качестве имени модели, а функция GetAll — что-то вроде этого:

 func getAll(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "application/json")
    vars := mux.Vars(r)
    model = vars["model"] // the model slug
    
    json.NewEncoder(w).Encode(model)
}
  

но это вообще не работает, потому что модель известна как String вместо struct Mcustm.
Я погуглил, чтобы решить эту проблему, и, возможно, нашел какое-то хорошее решение, используя этот подход:

 package main

import (
    "fmt"
    "reflect"
)

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

func registerType(typedNil interface{}) {
    t := reflect.TypeOf(typedNil).Elem()
    typeRegistry[t.PkgPath()   "."   t.Name()] = t
}

type MyString string
type myString string


func init() {
    registerType((*MyString)(nil))
    registerType((*myString)(nil))
    // ...
}

func makeInstance(name string) interface{} {
    return reflect.New(typeRegistry[name]).Elem().Interface()
}

func main() {
    for k := range typeRegistry {
        fmt.Println(k)
    }
    fmt.Printf("%Tn", makeInstance("main.MyString"))
    fmt.Printf("%Tn", makeInstance("main.myString"))
}
  

но все еще не решает мою проблему, потому что в функции init() мы должны вручную ввести для RegisterType структуру. Если у меня есть строка массива с именем структуры, как я могу динамически регистрировать тип, используя этот массив?

извините за мой плохой английский

Комментарии:

1. Пожалуйста, ознакомьтесь с Go для изучения основ языка, таких как пакеты и доступность.

2. спасибо за ваш ответ @mkopriva, я импортировал все необходимые пакеты, когда пробовал ту mcustm = models.Mcustm или fmt.Println(reflect.TypeOf(mcustm)) иную результирующую модель. Mcustm это означает, что моя структура была доступна для чтения во время выполнения. Но я хочу, чтобы он был динамическим

3. «Если у меня есть строка массива с именем структуры, как я могу динамически регистрировать тип, используя этот массив?» Вы не можете создавать типы из строки в Go, вам нужен реестр, и он должен иметь доступ к соответствующим типам Go, одних строк недостаточно. Единственный способ, который я могу придумать, позволяющий использовать только строки, — это использовать генератор кода, который принимает массив строк и создает реестр, однако это должно быть выполнено перед компиляцией.

4. GO не может генерировать типы динамически