Example: https://github.com/kazuki-ma/golang-enum-example
TL;DR
- Go に組み込みの Enum は無い。。。 OMG...
-
Apache Thrift 使って生成するとよい。
- Enum の書き方はThrift Missing Guide#Enums が詳しい
Example
人間が書く物
enum.thrift
enum Gender {
Unknown = 0,
Male = 1,
Female = 2,
}
機械生成されたコード
thrift --gen go pass_to_thrift_file.thrift
// Autogenerated by Thrift Compiler (0.12.0)
// DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING
package enum
// 前略
type Gender int64
const (
Gender_Unknown Gender = 0
Gender_Male Gender = 1
Gender_Female Gender = 2
)
func (p Gender) String() string {
switch p {
case Gender_Unknown:
return "Unknown"
case Gender_Male:
return "Male"
case Gender_Female:
return "Female"
}
return "<UNSET>"
}
func GenderFromString(s string) (Gender, error) {
switch s {
case "Unknown":
return Gender_Unknown, nil
case "Male":
return Gender_Male, nil
case "Female":
return Gender_Female, nil
}
return Gender(0), fmt.Errorf("not a valid Gender string")
}
func GenderPtr(v Gender) *Gender { return &v }
func (p Gender) MarshalText() ([]byte, error) {
return []byte(p.String()), nil
}
func (p *Gender) UnmarshalText(text []byte) error {
q, err := GenderFromString(string(text))
if err != nil {
return err
}
*p = q
return nil
}
func (p *Gender) Scan(value interface{}) error {
v, ok := value.(int64)
if !ok {
return errors.New("Scan value is not int64")
}
*p = Gender(v)
return nil
}
func (p *Gender) Value() (driver.Value, error) {
if p == nil {
return nil, nil
}
return int64(*p), nil
}
他の解決法 - Stringer
人間が書く物
pill.go
type Pill int
const (
Placebo Pill = iota
Aspirin
Ibuprofen
Paracetamol
Acetaminophen = Paracetamol
)
機械生成されるコード
pill_string.go
// Code generated by "stringer -type=Pill"; DO NOT EDIT.
package main
import "strconv"
func _() {
// An "invalid array index" compiler error signifies that the constant values have changed.
// Re-run the stringer command to generate them again.
var x [1]struct{}
_ = x[Placebo-0]
_ = x[Aspirin-1]
_ = x[Ibuprofen-2]
_ = x[Paracetamol-3]
}
const _Pill_name = "PlaceboAspirinIbuprofenParacetamol"
var _Pill_index = [...]uint8{0, 7, 14, 23, 34}
func (i Pill) String() string {
if i < 0 || i >= Pill(len(_Pill_index)-1) {
return "Pill(" + strconv.FormatInt(int64(i), 10) + ")"
}
return _Pill_name[_Pill_index[i]:_Pill_index[i+1]]
}
Stringer との差
- Thrift だと
MarshalText,UnmarshalTextがあるので JSON 対応 - Thrift だと
Scan,Valueがあるので int64 で DB 定義しておけばそのまま突っ込める(これは微妙かも)- go の MySQL Driver って全部 int64 で読むのか? あんまそこ気にしたことは無い。