如何在mongo-go-driver中将接口类型用作模型?

package code_test

import (
    "encoding/json"
    "fmt"
    "go.mongodb.org/mongo-driver/bson"
    "testing"
)

type Data struct {
    Type   int32   `bson:"Type"`
    IValue IGetter `bson:"IValue"`
}

func (m *Data) UnmarshalBSON(b []byte) error {
    tempData := &struct {
        Type int32 `bson:"Type"`
    }{}
    err := bson.Unmarshal(b, tempData)
    if err != nil {
        fmt.Println("A", err)
    }
    switch tempData.Type {
    case 100:
        reallyData := &struct {
            Type   int32    `bson:"Type"`
            IValue *AGetter `bson:"IValue"`
        }{}
        err = bson.Unmarshal(b, reallyData)
        m.Type = reallyData.Type
        m.IValue = reallyData.IValue
    }

    return nil
}

type IGetter interface {
    Get() string
    MarshalBSON() ([]byte, error)
}

type AGetter struct {
    DataA string
}

func (m *AGetter) Get() string {
    return "AGetter" + m.DataA
}
func (m *AGetter) MarshalBSON() ([]byte, error) {
    t := &struct {
        DataA string
    }{
        DataA: m.DataA,
    }
    return bson.Marshal(t)
    //return bson.Marshal(m)
}

func TestD(t *testing.T) {
    {
        data := &Data{
            Type: 100,
            IValue: &AGetter{
                DataA: "aaa",
            },
        }
        byteData, err := bson.Marshal(data)
        if err != nil {
            fmt.Println(err)
        }

        var after = &Data{}
        err = bson.Unmarshal(byteData, after)
        fmt.Printf("%s
", Stringify(after))
    }
}


func Stringify(o interface{}) string {
    //data, err := json.MarshalIndent(o, "", "  ")
    data, err := json.Marshal(o)
    if err != nil {
        //xlog.Error(err)
        return err.Error()
    }
    return string(data)
}

this code work success.

but i don't want to write MarshalBSON function.

just like in mgo driver: How to use interface type as a model in mgo (Go)?

It seems only UnmarshalBSON function is necessary.

But when I remove MarshalBSON in mongo-go-driver, I got an error "no encoder found for code_test.IGetter"


before find a good solution, I use this code to solve the problem...

package mongo_test_test

import (
    "fmt"
    mgoBson "github.com/globalsign/mgo/bson"
    "go.mongodb.org/mongo-driver/bson"
    "testing"
    "xkit"
)

type Data struct {
    Type   int32   `bson:"Type"`
    IValue IGetter `bson:"IValue"`
}

func (m *Data) UnmarshalBSON(b []byte) error {
    tempData := &struct {
        Type int32 `bson:"Type"`
    }{}
    err := bson.Unmarshal(b, tempData)
    if err != nil {
        fmt.Println("A", err)
    }
    switch tempData.Type {
    case 100:
        reallyData := &struct {
            Type   int32    `bson:"Type"`
            IValue *AGetter `bson:"IValue"`
        }{}
        err = bson.Unmarshal(b, reallyData)
        m.Type = reallyData.Type
        m.IValue = reallyData.IValue
    }

    return nil
}
func (m *Data) MarshalBSON() ([]byte, error) {
    return mgoBson.Marshal(m)
}

type IGetter interface {
    Get() string
}

type AGetter struct {
    DataA string
}

func (m *AGetter) Get() string {
    return "AGetter" + m.DataA
}

func TestD(t *testing.T) {
    {
        data := &Data{
            Type: 100,
            IValue: &AGetter{
                DataA: "aaa",
            },
        }
        byteData, err := bson.Marshal(data)
        if err != nil {
            fmt.Println(err)
        }

        var after = &Data{}
        err = bson.Unmarshal(byteData, after)
        fmt.Printf("%s
", xkit.Stringify(after))
    }
}