如何在golang中定义动态“类型结构”?

时间:2016-04-07 18:31:04

标签: go

这是Playground链接https://play.golang.org/p/qMKxqrOcc2。问题类似于Playground上的问题。

假设我有条件而且需要这样做:

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

其中AB是某些型号:

type A struct{
    filed1 string
    field2 string
    //etc

}

和模型B

type B struct{
    filed1 string
    field2 string
    //etc

}

AB中的字段有一些相同的字段,但大部分都反映了数据库表(文档),它们的类型相同(类型为struct)。

当我在所有人面前说:

var model interface{}

我收到了错误:

type models.A is not an expression 

我这样做是为了避免代码中的代码冗余,如果你问为什么。

问题类似于: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 --> somehow to concat modelName to this models?

这里是最新消息

我有两个型号Post和Product。他们俩都有照片领域。

type Post struct{

    Photos []string
    //etc
}

type Product {

    Photos []string
    //
}

现在我需要一个能说出这个的功能:

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
}

我可以理解我不能分配类型,但如何使用这一功能从不同类型中删除数据?据我所知,代码冗余将如下所示:

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

}

因为你只能区别为var model models.Post/var model models.Product。 这是代码中的冗余,它看起来很丑陋,但如果没有办法解决这个问题,那么我将完成这个冗余。

3 个答案:

答案 0 :(得分:5)

您无法指定类型。您必须分配实例。您的代码实际上必须是以下内容。我在你想要改变的两行中添加了评论。

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)
}

尽管如此,您可能不希望使用通用interface{}类型,而是更好地使用AB实现的实际接口。通用接口类型会让您更加头疼,并且真正违背使用像Go这样的静态类型语言的目的。

答案 1 :(得分:2)

您收到错误是因为您尝试将类型分配给interface{}实例。您需要分配一个实例。

如果你有;

var model interafce{}

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

然后它会正常工作。

答案 2 :(得分:1)

这是您使用界面类型实现编辑的程序:

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)
}

这里的移动部件是:

  • 用于定义具有泛型函数的接口的类型PhotoManager interface
  • AddPhotosPostProduct的实现,以提供接口函数的实际实现
  • pm PhotoManager用作AddPhotoToInterfaceImplementation的参数,以显示接口类型的用法。