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.
This is your program from the edit with a interface type implementation:
package main
import (
"log"
)
//// Interfaces ////
type PhotoManager interface {
AddPhotos(id string) (bool, error)
}
//// Post ////
type Post struct {
Photos []string
}
func (p *Post) AddPhotos(id string) (bool, error) {
p.Photos = append(p.Photos, id)
return true, nil
}
//// Product ////
type Product struct {
Photos []string
Docs []string
}
func (p *Product) AddPhotos(id string) (bool, error) {
p.Photos = append(p.Photos, id)
return true, nil
}
// Useless function to demonstrate interface usage //
func AddPhotoToInterfaceImplementation(id string, pm PhotoManager) {
pm.AddPhotos(id)
}
//// Main ////
func main() {
post := Post{}
product := Product{}
post.AddPhotos("123")
product.AddPhotos("321")
AddPhotoToInterfaceImplementation("456", &post)
AddPhotoToInterfaceImplementation("654", &product)
log.Println(post)
log.Println(product)
}
The moving parts here are:
PhotoManager interface
that is used to define an interface with generic functionsAddPhotos
on Post
and Product
to provide the actual implementations of the interface functionspm PhotoManager
as parameter to AddPhotoToInterfaceImplementation
to show the usage of the interface type.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.
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.