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.