1

我有一个 constutil 包,我在其中使用 iota 定义了一些 const 值。

package constutil

type UserType uint

const (
    Free UserType = iota + 1
    Premium UserType
    ...
)

json我会得到{"user": "Premium", ...}。现在我需要为Premium它保存用户的价值2。我试图得到这样的值:

constutil.(req.User)

但它没有像req.User返回string一样工作:"Premium".

我可以使用map[string]uint. 但是有什么方法可以使用iota吗?

4

2 回答 2

2

不要认为iota值和字符串之间有任何内置的映射方式。有一些工具可以生成用于映射的代码。

我遇到过类似的情况,当我不想依赖生成器或其他工具时,我做过类似的事情。希望它可以作为一些事情的开始。

https://play.golang.org/p/MxPL-0FVGMt

package main

import (
    "encoding/json"
    "fmt"
)

type UserType uint

const (
    UserTypeFree UserType = iota
    UserTypePremium
)

var UserTypeToString = map[UserType]string{
    UserTypeFree:    "Free",
    UserTypePremium: "Premium",
}

var UserTypeFromString = map[string]UserType{
    "Free":    UserTypeFree,
    "Premium": UserTypePremium,
}

func (ut UserType) String() string {
    if s, ok := UserTypeToString[ut]; ok {
        return s
    }
    return "unknown"
}

func (ut UserType) MarshalJSON() ([]byte, error) {
    if s, ok := UserTypeToString[ut]; ok {
        return json.Marshal(s)
    }
    return nil, fmt.Errorf("unknown user type %d", ut)
}

func (ut *UserType) UnmarshalJSON(text []byte) error {
    var s string
    if err := json.Unmarshal(text, &s); err != nil {
        return err
    }
    var v UserType
    var ok bool
    if v, ok = UserTypeFromString[s]; !ok {
        return fmt.Errorf("unknown user type %s", s)
    }
    *ut = v
    return nil
}

func main() {
    var ut UserType

    json.Unmarshal([]byte(`"Free"`), &ut)

    fmt.Printf("%#v %v \n", ut, ut)

    b, _ := json.Marshal(ut)

    fmt.Printf("%v\n", string(b))

}
于 2019-02-17T16:44:07.323 回答
1

对于此类枚举用例,最好使用 const 字符串。

type UserType string

const(
  Premium UserType = "Premium"
)

或者定义自定义编组/解组:

package main

import (
    "fmt"
    "encoding/json"
)

type UserType uint

func (u UserType) String() string{
    return "Premium"
}

const(
  Premium UserType = 1
)

type User struct{
    T UserType `json:"type"`
}

func (u *User) MarshalJSON() ([]byte, error) {
    return json.Marshal(&struct {
        T string
    }{
        T:    fmt.Sprint(u.T),
    })
}

func (u *User) UnmarshalJSON(data []byte) error {
    aux := &struct {
        T string `json:"type"`
    }{  }
    if err := json.Unmarshal(data, &aux); err != nil {
        return err
    }
    fmt.Println(aux.T)
    switch aux.T{
    case "Premium":
        u.T = Premium
    }
    return nil
}


func main() {
    b := []byte(`{"type":"Premium"}`)
    x := new(User)
    if err := json.Unmarshal(b, x); err != nil{
        fmt.Printf("err: %v\n", err)
    }
    fmt.Printf("unmasrshalled: %v\n", *x)
    fmt.Printf("type: %d\n", x.T)
    b, _ = json.Marshal(x)
    fmt.Printf("marshalled: %v\n", string(b))

}
于 2019-02-17T16:24:34.187 回答