任意类型添加方法
在Go语言中,接收者的类型可以是任何类型,不仅仅是结构体,任何类型都可以拥有方法。 举个例子,我们基于内置的int类型使用type关键字可以定义新的自定义类型,然后为我们的自定义类型添加方法。
//MyInt 将int定义为自定义MyInt类型
type MyInt int
//SayHello 为MyInt添加一个SayHello的方法
func (m MyInt) SayHello() {
fmt.Println("Hello, 我是一个int。")
}
func main() {
var m1 MyInt
m1.SayHello() //Hello, 我是一个int。
m1 = 100
fmt.Printf("%#v %T\n", m1, m1) //100 main.MyInt
}
Go
type Status int8
const (
Running Status = 1
Warning Status = 2
)
// 将方法名改为 MarshalJSON 即可让 json 包自动调用
func (s Status) MarshalJSON() (data []byte, err error) {
var str string
switch s {
case Running:
str = "运行中"
case Warning:
str = "警告"
default:
str = "未知"
}
return json.Marshal(str)
}
// 5. 添加反序列化支持
// 如果需要从 JSON 反序列化
func (s *Status) UnmarshalJSON(data []byte) error {
var str string
if err := json.Unmarshal(data, &str); err != nil {
return err
}
switch str {
case "运行中":
*s = Running
case "警告":
*s = Warning
default:
return fmt.Errorf("未知状态: %s", str)
}
return nil
}
// 这样 json.Marshal(user) 就会自动使用这个方法
type User struct {
ID int64
Name string `gorm:"size:32"`
Status Status `json:"status"`
}
最后调用:Marshal
// 调用 json.Marshal 时,会自动调用 MarshalJSON 方法
user := User{
ID: 1,
Name: "李四",
Status: Warning,
}
data, err = json.Marshal(user)
if err != nil {
panic(err)
}
fmt.Println(string(data)) // 输出: {"ID":1,"Name":"李四","status":"警告"}
// 反序列化调用示例 Unmarshal
func unmarshalExample() {
jsonStr := `{"ID":1,"Name":"张三","status":"运行中"}`
var user User
if err := json.Unmarshal([]byte(jsonStr), &user); err != nil {
panic(err)
}
fmt.Printf("用户状态: %d\n", user.Status) // 输出: 用户状态: 1
}
// 单独调用一种方法:
// 直接调用 MarshalJSON 方法
runningStatus := Running
data, err := runningStatus.MarshalJSON()
if err != nil {
panic(err)
}
fmt.Println("Running OldName:", string(data)) // 输出: "运行中"
扩展建议:可以考虑为 Status 类型添加字符串方法,便于直接输出:
Go
type Status int8
const (
Running Status = 1
Warning Status = 2
)
user := User{
Name: "赵六",
Status: Warning,
}
func (s Status) String() string {
switch s {
case Running:
return "运行中"
case Warning:
return "警告"
default:
return "未知"
}
}
// 使用示例
func stringExample() {
user := User{Status: Running}
fmt.Println(user.Status.String()) // 输出: 运行中
}