英文:
How to return dynamic type struct in Golang?
问题
我正在使用Golang Revel进行一些Web项目,到目前为止已经完成了12个项目。在所有这些项目中,由于返回类型的原因,我有很多代码冗余。看看这两个函数:
func (c Helper) Brands() []*models.Brand{
//在rethinkdb上执行一些查询,并填充正确的模型
var brands []*models.Brand
rows.All(&brands)
return brands
}
func (c Helper) BlogPosts() []*models.Post{
//在rethinkdb上执行一些查询,并填充正确的模型
var posts []*models.Post
rows.All(&posts)
return posts
}
如你所见,它们都返回相同类型的数据(结构体类型)。
我的想法是只传递一个字符串变量,像这样:
func (c Helper) ReturnModels(modelName string) []*interface{} {
//使用modelName进行rethinkdb查询,并返回modelName的[]*interface{}
}
这样,我可以只有一个辅助函数来返回不同模型但相同数据类型的数据,而不是为不同模型重复相同的操作。
我的问题是:
- 这种做法是否可行?
- 如果是,你能指导我查阅正确的文档吗?
- 如果不行,我将非常乐意听取你的答案
英文:
I am using Golang Revel for some web project and I did like 12 projects in that so far. In all of them I have a lot of code redundancy because of return types. Look at this two functions:
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
}
As you can see they they both returns same type of data (type struct).
My idea was just to pass string var like this:
func (c Helper) ReturnModels(modelName string) []*interface{} {
//do rethinkdb select with modelName and return []*interface{} for modelName
}
Like this I can have just one helper for returning data types instead of
doing same thing over and over again for different models but same data type.
My questions are:
- Is this possible at all
- If yes can you point me to right docs
- If no, I will be more then happy to return your answer
答案1
得分: 47
是的,这是可能的,但是你的函数应该返回interface{}
而不是[]*interface
。
func (c Helper) ReturnModels(modelName string) interface{} {}
在这种情况下,你可以使用类型切换和/或类型断言将返回值转换为其原始类型。
示例
注意:我从未使用过Revel,但以下代码片段应该给你一个大致的想法:
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]
}
英文:
Yes it's possible however your function should return interface{}
and not []*interface
.
func (c Helper) ReturnModels(modelName string) interface{} {}
In this case you could use Type Switches and/or Type Assertions to cast the return value into it's original type.
Example
Note: I've never used Revel, but the following snippet should give you an a general idea:
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]
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论