0
votes

When using mongo-driver, I have this struct which I pass to the get function as interface{}. The problem is when I use the Decode method, it returns a map while I was expecting a struct of the proper type. I found a similar question here but the solution didnt work for me, the program crashes.

type Item struct {
 //whatever
}

type mymodel struct {
    I            interface{} 
    F            interface{}
    DatabaseName string
    Collection   string
}

func Do(){
    var item Item
    var filter Item

    m:= mymodel{I: item, F: filter}
    res,_ := get(m)
}

func get(m mymodel) (*interface{}, error) {

    c := database.DBCon.Database("whatever").Collection("whatever")

    ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
    err := c.FindOne(ctx, m.F).Decode(&m.I)
    if err != nil {
        log.Log.Info(err)
        return nil, err
    }


    return &m.I, nil

}
1
You need to make the interface fields I and F store a pointer (maybe not F since you're not decoding anything into that), and then pass them directly to Decode, without anymore &. That is m:= mymodel{I: &item, F: &filter}, and then .Decode(m.I). - mkopriva
that worked perfectly! many thanks. If you post it as an answer ill mark it as accepted. - Battalgazi

1 Answers

1
votes

You need to make the interface fields I and F store a pointer to the instance into which you want to decode the data (maybe not F since you're not decoding anything into that), and then pass them directly to Decode, without any more address operations (&x).

For example:

func Do(){
    var item Item
    var filter Item

    m:= mymodel{I: &item, F: filter}
    res,_ := get(m)
}

func get(m mymodel) (*interface{}, error) {
    c := database.DBCon.Database("whatever").Collection("whatever")

    ctx, _ := context.WithTimeout(context.Background(), 5*time.Second)
    err := c.FindOne(ctx, m.F).Decode(m.I)
    if err != nil {
        log.Log.Info(err)
        return nil, err
    }

    return &m.I, nil
}