如何将数据反序列化为接口类型?

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

How to Unmarshall to interface type?

问题

我已经构建了一个小例子来说明我想要做的事情:

type Service interface {
	Transform()
}

type XYZ struct {
	ID string `json:"id"`
}

func (s XYZ) Transform() {}

func main() {
	x := "could be anything"
	msg := []byte(`{"id": "123"}`)

	var msgS Service

	switch x {
	case "could be anything":
		msgS = XYZ{}
		break
	case "could be something else":
		// another type that implements Transform()
		break
	}

	err := json.Unmarshal(msg, &msgS)

	if err != nil {
		fmt.Println(err)
	}

	// msgS.Transform()
}

这会返回一个错误:

json: cannot unmarshal object into Go value of type main.Service

基本上,我需要根据x可能包含的内容来灵活处理。如果我将msgS实例化为实际实现Transform()的类型,一切都按预期工作。

我意识到我可能需要重新考虑整个实现 - 欢迎任何想法!

英文:

I have constructed a small example of what I am trying to do:

type Service interface {
	Transform()
}

type XYZ struct {
	ID string `json:"id"`
}

func (s XYZ) Transform() {}

func main() {
	x := "could be anything"
	msg := []byte(`{"id": "123"}`)

	var msgS Service

	switch x {
	case "could be anything":
		msgS = XYZ{}
		break
	case "could be something else":
		// another type that implements Transform()
		break
	}

	err := json.Unmarshal(msg, &msgS)

	if err != nil {
		fmt.Println(err)
	}

	// msgS.Transform()
}

Go Playground

This returns an error:

json: cannot unmarshal object into Go value of type main.Service

Essentially, I need to be flexible with whatever x might hold, hence the switch. If I instantitate msgSto the actual type that implements Transform(), all works as expected.

I realise I might need to reconsider my whole implementation - Any ideas would be welcome!

答案1

得分: 2

你应该将其反序列化为具体类型,然后将结果赋值给接口类型。

一个简单的例子:

var service Service
var err error

switch x {
    case "something":
        var something Something // 这个实现了Service接口
        err = json.Unmarshal(data, &something)
        service = something
    case "something else":
        var somethingElse SomethingElse // 这个实现了Service接口
        err = json.Unmarshal(data, &somethingElse)
        service = somethingElse
    // 其他情况...
}

if err != nil {
    // 处理错误(可以在此处处理,或者在每个case内部处理,根据需要/喜好而定)
}

// 在这里根据需要使用service
英文:

You should unmarshal to the concrete type and then you can assign the result to the interface type.

A simple example:

var service Service
var err error

switch x {
    case "something":
        var something Something // this implements Service
        err = json.Unmarshal(data, &something)
        service = something
    case "something else":
        var somethingElse SomethingElse // this implements Service
        err = json.Unsmarshal(data, &somethingElse)
        service = somethingElse
    // etc...
}

if err != nil {
    // handle error (here or inside of each case if you need/want to)
}

// use service as needed here

huangapple
  • 本文由 发表于 2022年11月15日 02:46:58
  • 转载请务必保留本文链接:https://go.coder-hub.com/74436443.html
匿名

发表评论

匿名网友

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

确定