将映射转换为结构

好吧,标题有点误导。我所追求的如下:


type MyStruct struct {

    id   int

    name string

    age  int

}


func CreateFromMap(m map[string]interface{}) (MyStruct, error) {

    var (

        id   int

        name string

        age  int

        ok   bool

    )

    err := errors.New("Error!")

    id, ok = m["id"].(int)

    if !ok {

        return nil, err

    }

    name, ok = m["name"].(string)

    if !ok {

        return nil, err

    }

    age, ok = m["age"].(int)

    if !ok {

        return nil, err

    }

    return MyStruct{id, name, age}, nil

}

不要问:为什么我不使用CreateFromMap(int, string, int). 那个物体来自其他地方,不在我的控制范围内。


将映射中的每个键值对映射到结构体属性已经很无聊了。但是ok在每次转换后检查是否一切正常是混乱的。


除了反射之外,还有没有更简单的方法可以做到这一点?


拉风的咖菲猫
浏览 130回答 2
2回答

繁星coding

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

jeck猫

你可以只编组/解组,但属性名称应该匹配func CreateFromMap(m map[string]interface{}) (MyStruct, error) {&nbsp; &nbsp; data, _ := json.Marshal(m)&nbsp; &nbsp; var result MyStruct&nbsp; &nbsp; err := json.Unmarshal(data, &result)&nbsp; &nbsp; return result, err}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go