2 回答
TA贡献1797条经验 获得超4个赞
假设我假设您不想使用反射,因为您不想自己做。在这种情况下,如何使用为您执行此操作的外部包?
package main
import "fmt"
import "github.com/mitchellh/mapstructure"
type MyStruct struct {
Id int
Name string
Age int
}
func main() {
var m = make(map[string]interface{})
m["Id"] = 17
m["Name"] = "foo"
m["Age"] = 42
fmt.Printf("%+v\n", m)
res, err := CreateFromMap(m)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%+v\n", res)
}
func CreateFromMap(m map[string]interface{}) (MyStruct, error) {
var result MyStruct
err := mapstructure.Decode(m, &result)
return result, err
}
输出:
map[Age:42 Name:foo Id:17]
{Id:17 Name:foo Age:42}
无论您的结构是什么样子,它都有优势,但它在内部使用反射。实际上,如果不对结构的每个属性使用反射和/或重复代码,我看不到任何“好”的方法来做您想做的事情。但是,缺点是您必须使用大写的属性,以便将它们导出到外部包。
编辑(在评论中回答您的问题):
在我看来,如果要在“创建”结构时指定附加规则,应该在解码操作之后。例如:
func CreateFromMap(m map[string]interface{}) (MyStruct, error) {
var result MyStruct
err := mapstructure.Decode(m, &result)
if err != nil {
return result, err
}
if result.Age <= 0 {
result.Age = 0
}
if result.Name == "" {
return result, errors.New("empty name is not allowed")
}
return result, err
}
这样,您将清楚地将“转换”部分与您的结构的特定规则处理分开。
TA贡献1909条经验 获得超7个赞
你可以只编组/解组,但属性名称应该匹配
func CreateFromMap(m map[string]interface{}) (MyStruct, error) {
data, _ := json.Marshal(m)
var result MyStruct
err := json.Unmarshal(data, &result)
return result, err
}
- 2 回答
- 0 关注
- 129 浏览
添加回答
举报