3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Go で Enum をやるために:String(), FromString() 対応は Stringer よりも Apache Thrift を使うと便利で楽

Last updated at Posted at 2019-04-20

Example: https://github.com/kazuki-ma/golang-enum-example

TL;DR

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 定義しておけばそのまま突っ込める(これは微妙かも)

その他

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?