Mongodb由unmarshal获取堆栈溢出

I want to use mongodb in golang and wrote an sample application:

package main

import (
    "fmt"
    "labix.org/v2/mgo"
    "labix.org/v2/mgo/bson"
    "os"
)

type Session struct {
    Id   bson.ObjectId          `bson:"_id"`
    Data map[string]interface{} `bson:"data"`
}

func (rcv *Session) SetBSON(raw bson.Raw) error {
    return raw.Unmarshal(rcv)
}


type Authen struct {
    Name  string `bson:"name"`
    Email string `bson:"email"`
}

func main() {
    uri := "mongodb://localhost/"
    if uri == "" {
        fmt.Println("no connection string provided")
        os.Exit(1)
    }

    sess, err := mgo.Dial(uri)
    if err != nil {
        fmt.Printf("Can't connect to mongo, go error %v
", err)
        os.Exit(1)
    }
    defer sess.Close()

    sess.SetSafe(&mgo.Safe{})
    collection := sess.DB("test").C("sess")

    a := &Authen{Name: "Cormier", Email: "cormier@example.com"}
    s := &Session{}
    s.Id = bson.NewObjectId()
    s.Data = make(map[string]interface{})
    s.Data["logged"] = a

    err = collection.Insert(s)
    if err != nil {
        fmt.Printf("Can't insert document: %v
", err)
        os.Exit(1)
    }

    c := &Session{}
    c.Id = bson.NewObjectId()
    c.Data = make(map[string]interface{})

    err = sess.DB("test").C("sess").Find(bson.M{}).One(c)
    if err != nil {
        fmt.Printf("got an error finding a doc %v
")
        os.Exit(1)
    }

}

Insert into mongodb works like a charm, but to unmarshal back to reference I've got following panic:

runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow

runtime stack:
runtime.throw(0x6d84d9)
        c:/go/src/runtime/panic.go:491 +0xad
runtime.newstack()
        c:/go/src/runtime/stack.c:784 +0x5ef
runtime.morestack()
        c:/go/src/runtime/asm_amd64.s:324 +0x86

What am I doing wrong?

This logic introduces an infinite recursion:

func (rcv *Session) SetBSON(raw bson.Raw) error {
    return raw.Unmarshal(rcv)
}

Session implements the Setter interface, which means its unmarshaling happens via its SetBSON method, which is implemented by asking the bson package to unmarshal itself, which will do that by calling its SetBSON method. This never ends, until the stack space is over.

The solution is, of course, to not implement custom unmarshaling of Session by just asking the bson package to unmarshal it again.