如何在Golang中返回动态类型结构体?

31

我正在使用Golang Revel进行一些Web项目,到目前为止已经完成了12个项目。在所有这些项目中,由于返回类型,我都有很多代码冗余。看一下这两个函数:

func (c Helper) Brands() []*models.Brand{

    //do some select on rethinkdb and populate correct model
    var brands []*models.Brand
    rows.All(&brands)

    return brands

}

func (c Helper) BlogPosts() []*models.Post{

    //do some select on rethinkdb and populate correct model
    var posts []*models.Post
    rows.All(&posts)

    return posts

}

正如您所看到的,它们都返回相同类型的数据(类型为struct)。 我的想法只是像这样传递字符串变量:

func (c Helper) ReturnModels(modelName string) []*interface{} {

    //do rethinkdb select with modelName and return []*interface{} for modelName
}

像这样,我只需要一个帮助程序来返回数据类型,而不是为不同的模型但相同的数据类型一遍又一遍地做同样的事情。

我的问题是:

  1. 这个可能吗?
  2. 如果是,你能指导我查找正确的文档吗?
  3. 如果不行,我会很高兴返回你的答案 :)
1个回答

47

是可能的,但您的函数应该返回interface{}而不是[]*interface

func (c Helper) ReturnModels(modelName string) interface{} {}

在这种情况下,您可以使用类型开关(Type Switches)和/或类型断言(Type Assertions)将返回值强制转换为其原始类型。

示例

注意:我从未使用过Revel,但以下代码段应该让您有一个大致的想法:

Playground

package main

import "fmt"

type Post struct {
    Author  string
    Content string
}

type Brand struct {
    Name string
}

var database map[string]interface{}

func init() {
    database = make(map[string]interface{})

    brands := make([]Brand, 2)
    brands[0] = Brand{Name: "Gucci"}
    brands[1] = Brand{Name: "LV"}

    database["brands"] = brands

    posts := make([]Post, 1)
    posts[0] = Post{Author: "J.K.R", Content: "Whatever"}

    database["posts"] = posts
}

func main() {
    fmt.Println("List of Brands: ")
    if brands, ok := ReturnModels("brands").([]Brand); ok {
        fmt.Printf("%v", brands)
    }

    fmt.Println("\nList of Posts: ")
    if posts, ok := ReturnModels("posts").([]Post); ok {
        fmt.Printf("%v", posts)
    }

}

func ReturnModels(modelName string) interface{} {

    return database[modelName]
}

你能在如何实现它方面进一步扩展你的回答吗? - OscarRyz
6
你真是太棒了!我随时都可以给你擦鞋 : )。当我不知道如何做某事时,我讨厌有冗余的东西。你写的内容刚好从我的项目中移除了很多代码。 - pregmatch
4
请注意,如果类型断言失败, ReturnModels("brands").([]Brand) 将会触发 panic。在这种情况下,你应该断言为 []*models.Brand。使用逗号 ok 习惯用法可以防止 panic 事件的发生:https://golang.org/doc/effective_go.html#interface_conversions。 - elithrar
太好了!我已经更新了我的示例,包括“逗号,ok”模式。 - W.K.S
我刚刚删除了5个多余的方法文件。太好了。 - pregmatch

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接