Go 中的枚举

数据库中使用了枚举 enum 来存储订单状态 orders.state,然后在 model/order.go 中一堆状态常量:


type Order struct {
	// ...
	State string
}

const (
	OrderStatePending	= "pending"
	OrderStateLocked	= "locked"
	OrderStatePaid		= "paid"
	OrderStateRevoked	= "revoked"
	OrderStateDone		= "done"
)

既然说到 Go 的枚举,肯定有人要说 iota 了,那么,,用 iota 来实现该功能试试:

package model

import "database/sql/driver"

type orderState int

const (
	OrderStatePending orderState = iota
	OrderStateLocked
	OrderStatePaid
	OrderStateRevoked
	OrderStateDone
)

func (state orderState) String() string {
	return [...]string{"pending", "locked", "paid", "revoked", "done"}[state]
}

// 为了在 GORM 中正确读取值,还得为 orderState 类型实现 Value()、Scan()
func (state orderState) Value() (driver.Value, error) {
	return state.String(), nil
}

func (result *orderState) Scan(data interface{}) error {
	tab := [...]string{"pending", "locked", "paid", "revoked", "done"}
	if b, ok := data.([]byte); ok {
		for k, v := range tab {
			if v == string(b) {
				*result = orderState(k)
			}
		}
	}
	return nil
}

一看这代码量,算了,还是老老实实用第一种方式吧。

这时候就有点羡慕隔壁 swift 的枚举了:

import Foundation

enum state:String {
    case pending = "pending-val"
    case done = "done-val"
}

let s = state.pending
print(s.rawValue)