Mongodb通过unmarshal得到了堆栈溢出

时间:2015-03-06 15:06:02

标签: go mgo

我想在golang中使用mongodb并编写了一个示例应用程序:

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\n", 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\n", 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\n")
        os.Exit(1)
    }

}

插入mongodb的工作就像一个魅力,但要解散参考我有以下恐慌:

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

我做错了什么?

1 个答案:

答案 0 :(得分:4)

这个逻辑引入了无限递归:

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

Session实现了Setter接口,这意味着它的解组通过其SetBSON方法发生,该方法是通过要求bson包解组自己实现的,这将执行通过调用其SetBSON方法。这永远不会结束,直到堆栈空间结束。

当然,解决方案是不要通过让Session包再次解组它来实现bson的自定义解组。