Search code examples
restgocontrollerresourcesrevel

Trying to convert string to instance variable


I'm new to GO language. Trying to learn GO by building real web application. I'm using revel framework.

And here is my resource routes:

GET     /resource/:resource                     Resource.ReadAll
GET     /resource/:resource/:id                 Resource.Read
POST    /resource/:resource                     Resource.Create
PUT     /resource/:resource/:id                 Resource.Update
DELETE  /resource/:resource/:id                 Resource.Delete

for example:

GET /resource/users calls Resource.ReadAll("users")

And this is my Resource controller (it's just a dummy actions for now):

type Resource struct {
    *revel.Controller
}

type User struct {
    Id int
    Username string
    Password string
}

type Users struct {}

func (u Users) All() string {
        return "All"
}

func (c Resource) ReadAll(resource string) revel.Result {
    fmt.Printf("GET %s", resource)
    model := reflect.New(resource)
    fmt.Println(model.All())
    return nil
}

I'm trying get instance of Users struct by converting resource string to object to call All function.

and the error:

cannot use resource (type string) as type reflect.Type in argument to reflect.New: string does not implement reflect.Type (missing Align method)

I'm new to GO please don't judge me :)


Solution

  • Your problem is here:

    model := reflect.New(resource)
    

    You can't instantiate a type from a string that way. You need to either use a switch there and do stuff depending on the model:

    switch resource {
    case "users":
        model := &Users{}
        fmt.Println(model.All())
    case "posts":
        // ...
    }
    

    Or use reflect correctly. Something like:

    var types = map[string]reflect.Type{
        "users": reflect.TypeOf(Users{}) // Or &Users{}.
    }
    
    // ...
    
    model := reflect.New(types[resource])
    res := model.MethodByName("All").Call(nil)
    fmt.Println(res)