英文:
How to define dynamic "type struct" in golang?
问题
这是Playground链接https://play.golang.org/p/qMKxqrOcc2。问题与Playground上的问题类似。
假设我有一个条件需要执行以下操作:
if modelName == "a"{
model = models.A
}
else{
model = models.B
}
其中A
和B
是一些模型:
type A struct{
filed1 string
field2 string
//等等
}
和模型B
是
type B struct{
filed1 string
field2 string
//等等
}
A
和B
中的字段有一些相同的字段,但大多数反映了数据库表(文档),它们是相同类型的(结构体类型)。
当我在所有这些之前说:
var model interface{}
我得到错误:
type models.A is not an expression
我这样做是为了避免代码中的冗余,如果你问为什么。
问题类似于这个:https://stackoverflow.com/questions/35657362/how-to-return-dynamic-type-struct-in-golang
这是代码的更新:
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)
我知道这很愚蠢,可能不可能做到,但有没有办法做到这一点:
var model models.modelName --> 以某种方式将modelName连接到这个models中?
这是新的更新
我有两个模型Post和Product。它们都有Photos字段。
type Post struct{
Photos []string
//等等
}
type Product {
Photos []string
//
}
现在我需要一个函数来做到这一点:
func () RemovePhotos(id string, modelName string){
//如果modelName=="post"
//使用id获取post模型
//如果modelName=="product"
//使用id获取product模型
//设置model.Photos = []string
//在数据库中更新model
}
我知道我不能分配类型,但如何使用这个函数来从不同类型中删除数据?据我所见,代码冗余将如下所示:
func () RemovePhotos(id string, modelName string) return bool{
if modelName == "post"{
var model models.Post
modelWithdata := getModelWithId.(*model)
modelWithdata.Photos = []string
//在这里更新数据库中的model
}
if modelName == "product"{
var model models.Product
modelWithdata := getModelWithId.(*model)
modelWithdata.Photos = []string
//在这里更新数据库中的model
}
//我返回什么并不重要,这只是冗余的示例
return true
}
你可以看到唯一的区别是var model models.Post/var model models.Product
。
这是代码中的冗余,看起来很丑,但如果没有办法解决这个问题,那么好吧,我将接受这个带有冗余的解决方案。
英文:
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: https://stackoverflow.com/questions/35657362/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.
答案1
得分: 6
你不能分配类型,而是要分配实例。你的代码应该如下所示。我在两行代码中添加了注释,你需要更改这两行。
package main
import "fmt"
type B struct {
field1 string
field2 string
// etc
}
type A struct {
field1 string
field2 string
// etc
}
func main() {
var model interface{}
modelName := "b"
if modelName == "a" {
model = A{} // 注意这里的{}
} else {
model = B{} // 同样在这里
}
fmt.Println(model)
}
只是提个建议,你可能不想使用通用的 interface{}
类型,而是最好使用一个实际的接口,让 A
和 B
都实现它。通用的接口类型会给你带来更多麻烦,而且真正违背了使用静态类型语言如 Go 的目的。
英文:
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.
答案2
得分: 2
你之所以出现错误,是因为你试图给interface{}
实例分配一个类型。你需要给它分配一个实例。
如果你这样写:
var model interface{}
if modelName == "a"{
model = models.A{}
}
else{
model = models.B{}
}
那么它就会正常工作。
英文:
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.
答案3
得分: 1
这是你的程序,使用了接口类型的实现:
package main
import (
"log"
)
//// 接口 ////
type PhotoManager interface {
AddPhotos(id string) (bool, error)
}
//// 帖子 ////
type Post struct {
Photos []string
}
func (p *Post) AddPhotos(id string) (bool, error) {
p.Photos = append(p.Photos, id)
return true, nil
}
//// 产品 ////
type Product struct {
Photos []string
Docs []string
}
func (p *Product) AddPhotos(id string) (bool, error) {
p.Photos = append(p.Photos, id)
return true, nil
}
// 用于演示接口使用的无用函数 //
func AddPhotoToInterfaceImplementation(id string, pm PhotoManager) {
pm.AddPhotos(id)
}
//// 主函数 ////
func main() {
post := Post{}
product := Product{}
post.AddPhotos("123")
product.AddPhotos("321")
AddPhotoToInterfaceImplementation("456", &post)
AddPhotoToInterfaceImplementation("654", &product)
log.Println(post)
log.Println(product)
}
这里的关键部分是:
PhotoManager
接口类型,用于定义具有通用函数的接口Post
和Product
上的AddPhotos
实现,提供接口函数的实际实现AddPhotoToInterfaceImplementation
函数中的pm PhotoManager
参数,展示了接口类型的使用方式。
英文:
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:
- the type
PhotoManager interface
that is used to define an interface with generic functions - the implementations of
AddPhotos
onPost
andProduct
to provide the actual implementations of the interface functions - the usage of
pm PhotoManager
as parameter toAddPhotoToInterfaceImplementation
to show the usage of the interface type.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论