这是Go语言中的方法重写的示例吗?

huangapple go评论95阅读模式
英文:

Is this example of method overriding in Go?

问题

这段代码是一个Go语言中的JSON自定义编解码示例。在这段代码中,MarshalJSONUnmarshalJSON方法是为了实现自定义的JSON编解码逻辑。

在代码中,MarshalJSON方法被定义在Animal类型上,用于将Animal类型的值转换为JSON格式的字节切片。UnmarshalJSON方法也被定义在Animal类型上,用于将JSON格式的字节切片解码为Animal类型的值。

这两个方法并不是直接调用的,而是在调用json.Marshaljson.Unmarshal函数时由Go语言的反射机制自动调用的。当调用json.Marshal函数时,会检查类型是否实现了MarshalJSON方法,如果实现了,则会调用该方法进行自定义的编码逻辑;同样地,当调用json.Unmarshal函数时,会检查类型是否实现了UnmarshalJSON方法,如果实现了,则会调用该方法进行自定义的解码逻辑。

这种方式并不是传统意义上的方法重写,而是通过实现特定的接口方法来实现自定义的编解码逻辑。这是Go语言中利用接口和反射机制实现的一种灵活的方式。

希望能帮助你理解这段代码!如果还有其他问题,请随时提问。

英文:
package main

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

type Animal int

const (
	Unknown Animal = iota
	Gopher
	Zebra
)

func (a *Animal) UnmarshalJSON(b []byte) error {
	var s string
	if err := json.Unmarshal(b, &s); err != nil {
		return err
	}
	switch strings.ToLower(s) {
	default:
		*a = Unknown
	case "gopher":
		*a = Gopher
	case "zebra":
		*a = Zebra
	}

	return nil
}

func (a Animal) MarshalJSON() ([]byte, error) {
	var s string
	switch a {
	default:
		s = "unknown"
	case Gopher:
		s = "gopher"
	case Zebra:
		s = "zebra"
	}

	return json.Marshal(s)
}

func main() {
	blob := `["gopher","armadillo","zebra","unknown","gopher","bee","gopher","zebra"]`
	var zoo []Animal
	if err := json.Unmarshal([]byte(blob), &zoo); err != nil {
		log.Fatal(err)
	}

	census := make(map[Animal]int)
	for _, animal := range zoo {
		census[animal] += 1
	}

	fmt.Printf("Zoo Census:\n* Gophers: %d\n* Zebras:  %d\n* Unknown: %d\n",
		census[Gopher], census[Zebra], census[Unknown])

}

This is the code snippet of Json custom marshal example in go doc. My question is where is the call to MarshalJSON and UnmarshalJSON method in this code. Are these method somehow overriding Json package's UnmarshalJSON and MarshalJSON method. I thought go does not support method overriding this way. Pls help, i am not able to understand what is happening in this code!!

答案1

得分: 2

根据文档所说:

要将JSON解组为实现Unmarshaler接口的值,Unmarshal会调用该值的UnmarshalJSON方法,即使输入是JSON null。

在json.Unmarshal的实现中,有类似以下代码的部分:

 u, ok := v.(Unmarshaler)
 if ok {
     err := u.Unmarshal(data)
     if err != nil { /* 处理错误 */ }
 } else {
     // 处理其他类型的值
 }

该代码使用了类型断言来确定该值是否满足json.Unmarshaler接口。如果该值满足该方法,就会调用该值的UnmarshalJSON函数。

(*Animal).UnmarshalJSON函数会被调用,因为*Animal满足json.Unmarshaler接口。

英文:

The documentation says:

> To unmarshal JSON into a value implementing the Unmarshaler interface, Unmarshal calls that value's UnmarshalJSON method, including when the input is a JSON null.

Somewhere in the json.Unmarshal implementation, there's code similar this:

 u, ok := v.(Unmarshaler)
 if ok {
     err := u.Unmarshal(data)
     if err != nil { /* handle error */}
 } else {
     // handle other kinds of values
 }

The code uses a type assertion to determine if the value satisfies the json.Unmarshaler interface. If the value does satisfy the method, the value's UnmarshalJSON function is called.

The (*Animal).UnmarshalJSON function is called because *Animal satisfies the json.Unmarshaler interface.

答案2

得分: 0

这是一个在不同包中实现接口的示例。

在Go语言中,不需要像Java或C++那样显式声明你正在实现一个接口。你只需要实现接口声明的所有函数即可。在这个例子中,你正在实现json中声明的Unmarshaler接口,该接口被Unmarshal函数使用。

英文:

This is an example of implementing an interface from a different package.

There's no need to explicitly declare that you're implementing an interface in Go, like there is in Java or C++ for example. You just have to implement all the functions it declares. In this case, you're implementing the Unmarshaler interface declared in the json package which is used by the Unmarshal function.

huangapple
  • 本文由 发表于 2022年5月11日 00:23:30
  • 转载请务必保留本文链接:https://go.coder-hub.com/72189884.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定