var session *mgo.Session
func main() {
session, err := mgo.Mongo("localhost")
if err != nil {
panic(err)
}
defer session.Close()
}
func register(values map[string][]string) (user *User, err error) {
// assume I'm initialising user correctly
c := session.DB("development").C("users")
err = c.Insert(&user)
return
}
011/11/11 04:47:47 http: panic serving 127.0.0.1:62204: runtime error: invalid memory address or nil pointer dereference
/Users/paddyforan/go/src/pkg/http/server.go:576 (0x2e58d)
_func_005: buf.Write(debug.Stack())
/Users/paddyforan/go/src/pkg/runtime/proc.c:1356 (0x11453)
panic: reflect·call(d->fn, d->args, d->siz);
/Users/paddyforan/go/src/pkg/runtime/runtime.c:128 (0x11e0a)
panicstring: runtime·panic(err);
/Users/paddyforan/go/src/pkg/runtime/darwin/thread.c:480 (0x165b4)
sigpanic: runtime·panicstring("invalid memory address or nil pointer dereference");
/Users/paddyforan/go/src/pkg/sync/atomic/asm_386.s:47 (0x114fbe)
AddUint32: LOCK
/Users/paddyforan/go/src/pkg/sync/rwmutex.go:30 (0xa9efb)
(*RWMutex).RLock: if atomic.AddInt32(&rw.readerCount, 1) < 0 {
/Users/paddyforan/package/Go/mgo/session.go:2369 (0x50162)
(*Session).acquireSocket: s.m.RLock()
/Users/paddyforan/package/Go/mgo/session.go:2477 (0x50555)
(*Session).writeQuery: socket, err := s.acquireSocket(false)
/Users/paddyforan/package/Go/mgo/session.go:1176 (0x4bec2)
Collection.Insert: _, err := c.DB.Session.writeQuery(&insertOp{c.FullName, docs})
/Users/paddyforan/package/Go/package/user.go:97 (0x314b)
register: err = c.Insert(&user)
/Users/paddyforan/package/Go/package/main.go:147 (0x2b3b)
openID: user, err := register(values)
/Users/paddyforan/go/src/pkg/http/server.go:686 (0x2536b)
HandlerFunc.ServeHTTP: f(w, r)
/Users/paddyforan/go/src/pkg/http/server.go:906 (0x25fca)
(*ServeMux).ServeHTTP: h.ServeHTTP(w, r)
/Users/paddyforan/go/src/pkg/http/server.go:652 (0x251e4)
(*conn).serve: handler.ServeHTTP(w, w.req)
/Users/paddyforan/go/src/pkg/runtime/proc.c:261 (0xfa5b)
goexit: runtime·goexit(void)
> I'm afraid I'm new to both Mongo and mgo, so I'll probably put plenty of my
> ignorance on display here. I would like to try and share a session between
> multiple functions in my program, and I seem to be running into
> difficulties. My first instinct was to create the session variable in the
> root of the script
This isn't what I'd do, but mostly because global state tends to be a
bad idea for a number of reasons, including making it harder to test
your application. That said, there's no reason for it to break.
>> func main() {
>> session, err := mgo.Mongo("localhost")
This is the bug. session here is a local variable rather than your
global "session" variable, so the global variable is never being
initialized (:= declares and assigns, while = assigns).
>> if err != nil {
>> panic(err)
>> }
>> defer session.Close()
>> }
This function main is opening and closing the session immediately, so
it doesn't really look realistic. How come your program is not
returning immediately?
> So my question is, really, what is the appropriate way to share a session
> across several different functions?
The best way is also the most obvious: pass it as a parameter.
> As a follow-up question, and here's where my ignorance of Mongo really
> shines, should I be forming a separate session for separate collections? In
> what situation is it recommended that I create a new session?
Don't worry, that's actually a relevant question, even more because
sessions are really a mgo concept rather than a MongoDB one.
If you're handling http requests, a good approach is to use a new
session for each request, by Copy-ing your original session. This will
ensure parallelism and isolation of errors.
--
Gustavo Niemeyer
http://niemeyer.net
http://niemeyer.net/plus
http://niemeyer.net/twitter
http://niemeyer.net/blog
-- I'm not absolutely sure of anything.
This isn't what I'd do, but mostly because global state tends to be a
bad idea for a number of reasons, including making it harder to test
your application. That said, there's no reason for it to break.
This is the bug. session here is a local variable rather than your
global "session" variable, so the global variable is never being
initialized (:= declares and assigns, while = assigns).
This function main is opening and closing the session immediately, so
it doesn't really look realistic. How come your program is not
returning immediately?
The best way is also the most obvious: pass it as a parameter.
If you're handling http requests, a good approach is to use a new
session for each request, by Copy-ing your original session. This will
ensure parallelism and isolation of errors.
You were right, it really depends, and designing the architecture of
your application in a way that fields get passed around taking the
responsibility of each area in account is an area that can't really be
explained or taught without practice and looking at individual cases
and examples.
I think you already got some advice on that area in the go-nuts
mailing list, right?