Skip to content
鼓励作者:欢迎打赏犒劳

go常量枚举

go没有这俩玩意,但是这俩玩意是真的好用啊,没有就自己实现一把。最佳实践!!!

常量

注意,这里显示了UnmarshalJSONMarshalJSON这两个方法,是为了在json序列化Status的时候,触发这两个函数,做出对应的逻辑判断。 其实可以忽略不写。解析成功在后面判断也行。

go
package main

import (
	"encoding/json"
	"fmt"
	"log"
)

// 1. 枚举定义(你的代码)
type Status string

const (
	StatusPending  Status = "pending"
	StatusApproved Status = "approved"
	StatusRejected Status = "rejected"
)

var AllStatus = []Status{StatusPending, StatusApproved, StatusRejected}

func (s Status) IsValid() bool {
	for _, v := range AllStatus {
		if v == s {
			return true
		}
	}
	return false
}

func (s Status) String() string {
	return string(s)
}

// JSON 支持(可选)
func (s Status) MarshalJSON() ([]byte, error) {
	return json.Marshal(string(s))
}
func (s *Status) UnmarshalJSON(data []byte) error {
	var str string
	if err := json.Unmarshal(data, &str); err != nil {
		return err
	}
	*s = Status(str)
	if !s.IsValid() {
		return fmt.Errorf("invalid status: %s", str)
	}
	return nil
}

// ========================================================================================
// 2. 订单结构体
type Order struct {
	ID     string `json:"id"`
	Name   string `json:"name"`
	Status Status `json:"status"`
}

// 3. 创建新订单(默认状态:pending)
func NewOrder(id, name string) *Order {
	return &Order{
		ID:     id,
		Name:   name,
		Status: StatusPending,
	}
}

// 4. 更新订单状态(带合法性校验)
func (o *Order) UpdateStatus(newStatus Status) error {
	if !newStatus.IsValid() {
		return fmt.Errorf("无效的订单状态: %s", newStatus)
	}
	o.Status = newStatus
	return nil
}

// 5. 打印订单信息
func (o *Order) Print() {
	fmt.Printf("📦 订单 ID: %s, 名称: %s, 状态: %s\n", o.ID, o.Name, o.Status)
}

func main() {
	// === 1. 创建订单 ===
	order := NewOrder("O1001", "iPhone 16")
	order.Print() // 状态: pending

	// === 2. 更新状态为 approved ===
	err := order.UpdateStatus(StatusApproved)
	if err != nil {
		log.Fatal(err)
	}
	order.Print() // 状态: approved

	// === 3. 尝试设置非法状态(演示校验)===
	err = order.UpdateStatus("cancelled") // ❌ 非法状态
	if err != nil {
		fmt.Printf("❌ 更新失败: %v\n", err)
	}

	// === 4. JSON 序列化(用于 API 输出)===
	data, err := json.Marshal(order)
	if err != nil {
		log.Fatal(err)
	}
	fmt.Printf("📤 JSON 输出: %s\n", data)
	// 输出: {"id":"O1001","name":"iPhone 16","status":"approved"}

	// === 5. JSON 反序列化(模拟 API 输入)===
	jsonInput := `{"id":"O1002", "name":"AirPods", "status":"rejected"}`
	var order2 Order
	err = json.Unmarshal([]byte(jsonInput), &order2)
	if err != nil {
		log.Fatal(err)
	}
	order2.Print() // 状态: rejected

	// === 6. 再次尝试反序列化非法状态 ===
	invalidJSON := `{"id":"O1003", "name":"非法订单", "status":"cancelled"}`
	var order3 Order
	err = json.Unmarshal([]byte(invalidJSON), &order3)
	if err != nil {
		fmt.Printf("❌ 反序列化失败: %v\n", err)
	} else {
		fmt.Printf("⚠️  警告:非法状态被接受: %s\n", order3.Status)
	}
}

结果

text
📦 订单 ID: O1001, 名称: iPhone 16, 状态: pending
📦 订单 ID: O1001, 名称: iPhone 16, 状态: approved
❌ 更新失败: 无效的订单状态: cancelled
📤 JSON 输出: {"id":"O1001","name":"iPhone 16","status":"approved"}
📦 订单 ID: O1002, 名称: AirPods, 状态: rejected
❌ 反序列化失败: invalid status: cancelled

枚举

go
package main

import (
	"fmt"
)

// 1. 定义枚举结构体
type OrderStatus struct {
	Code  int
	Desc  string
	Color string
}

// 2. 私有构造函数(确保只能通过预定义方式创建)
func newStatus(code int, desc, color string) OrderStatus {
	return OrderStatus{Code: code, Desc: desc, Color: color}
}

// 3. 定义枚举常量(全局变量)
var (
	OrderPending  = newStatus(100, "待处理", "yellow")
	OrderApproved = newStatus(200, "已批准", "green")
	OrderRejected = newStatus(400, "已拒绝", "red")
)

// 4. 所有枚举值列表(用于校验)
var AllOrderStatuses = []OrderStatus{
	OrderPending,
	OrderApproved,
	OrderRejected,
}

// 5. 实现 String() 方法
func (s OrderStatus) String() string {
	return s.Desc
}

// 6. 校验是否是合法枚举值
func (s OrderStatus) IsValid() bool {
	for _, valid := range AllOrderStatuses {
		if s == valid {
			return true
		}
	}
	return false
}

// 7. 根据 code 查找枚举项(可选)
func OrderStatusByCode(code int) (OrderStatus, bool) {
	for _, s := range AllOrderStatuses {
		if s.Code == code {
			return s, true
		}
	}
	return OrderStatus{}, false
}

func main() {
	// 1. 使用预定义枚举
	status := OrderApproved
	fmt.Printf("状态: %s\n", status)       // 输出: 状态: 已批准
	fmt.Printf("代码: %d\n", status.Code)  // 输出: 代码: 200
	fmt.Printf("颜色: %s\n", status.Color) // 输出: 颜色: green

	// 2. 校验
	if status.IsValid() {
		fmt.Println("✅ 合法状态")
	}

	// 3. 根据 code 查找
	if s, ok := OrderStatusByCode(100); ok {
		fmt.Printf("Code 100 对应: %s\n", s)
	}
}

结果

text
状态: 已批准
代码: 200
颜色: green
✅ 合法状态
Code 100 对应: 待处理

如有转载或 CV 的请标注本站原文地址