Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define dynamic "type struct" in golang?

Tags:

go

Here is Playground link https://play.golang.org/p/qMKxqrOcc2. Problem is similar to one that is on Playground.

Let's say I have a condition and need to do this:

if modelName == "a"{
    model = models.A
} 
else{
    model = models.B
}

where A and B are some models:

type A struct{
    filed1 string
    field2 string
    //etc

}

and model B is

type B struct{
    filed1 string
    field2 string
    //etc

}

Fields in A and B has some same fields but mostly they reflect database table (document) and they are of same type (type struct).

When I say in front of all that:

var model interface{}

I got error:

type models.A is not an expression 

I am doing this to avoid code redundancy in code if you are asking why.

Question is similar to this: How to return dynamic type struct in Golang?

Here is update for code:

b := c.mainHelper.GetModelBy("id", id, modelName).(map[string]interface{})
mapstructure.Decode(b, &model)

if modelName == "a"{
    model.Photos = []string{"ph1","ph2"}
}
if modelName == "b"{
    model.Docs = []string{"doc1","doc2"}
}

c.mainHelper.UpdateModel(product, id, modelName)

I know this is stupid and probably is impossible to do but is there and way to do this:

var model models.modelName --> somehow to concat modelName to this models?

HERE IS NEW UPDATE

I have two models Post and Product. Both of them has Photos field.

type Post struct{

    Photos []string
    //etc
}

type Product {

    Photos []string
    //
}

Now I need one function that will say this:

func () RemovePhotos(id string, modelName string){

//if modelName=="post"
    //get model post with id

//if modelName=="product"
    //get model product with id

//set model.Photos = []string
//update model in db
}

I can understand that I can not assign type but how to use this one function to remove data from differnt types? As far as I can see code redundancy will look like this:

func () RemovePhotos(id string, modelName string) return bool{

    if modelName == "post"{

      var model models.Post
      modelWithdata := getModelWithId.(*model)
      modelWithdata.Photos = []string
      //update model in db here
    } 
    if modelName == "product"{
      var model models.Product
      modelWithdata := getModelWithId.(*model)
      modelWithdata.Photos = []string
      //update model in db here
    }

    //it does not matter what I return this is just redundancy example
    return true

}

As you can only difference is var model models.Post/var model models.Product. This is redundancy in code and it looks ugly but if there is no way around this then ok, i will have this one completed with redundancy.

like image 743
pregmatch Avatar asked Nov 18 '25 11:11

pregmatch


2 Answers

You can't assign types. You have to assign instances. Your code will effectively have to be the following. I added comments in the two lines that you'll want to change.

package main

import "fmt"

type B struct {
    filed1 string
    field2 string
    //etc

}

type A struct {
    filed1 string
    field2 string
    //etc

}

func main() {
    var model interface{}
    modelName := "b"
    if modelName == "a" {
        model = A{} // note the {} here
    } else {
        model = B{} // same here
    }

    fmt.Println(model)
}

Just a word of advice though, you probably don't want to use a generic interface{} type, instead its better to use an actual interface that both A and B implements. The generic interface type will cause you more headaches and really defeats the purpose of using a statically typed language like Go.

like image 84
Will C Avatar answered Nov 20 '25 04:11

Will C


You're getting the error because you're trying to assign a type to the interface{} instance. You need to assign an instance.

If you instead had;

var model interafce{}

if modelName == "a"{
    model = models.A{}
} 
else{
    model = models.B{}
}

then it would work fine.

like image 33
evanmcdonnal Avatar answered Nov 20 '25 05:11

evanmcdonnal



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!