英文:
Is this example of method overriding in Go?
问题
这段代码是一个Go语言中的JSON自定义编解码示例。在这段代码中,MarshalJSON
和UnmarshalJSON
方法是为了实现自定义的JSON编解码逻辑。
在代码中,MarshalJSON
方法被定义在Animal
类型上,用于将Animal
类型的值转换为JSON格式的字节切片。UnmarshalJSON
方法也被定义在Animal
类型上,用于将JSON格式的字节切片解码为Animal
类型的值。
这两个方法并不是直接调用的,而是在调用json.Marshal
和json.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.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论