Issues retrieving MongoDB documents with Go
Question
I have the following code, and I'm not sure why it is not returning a slice of Notes. I am using the mgo library from labix.org to connect to MongoDB and following their online documentation.
type Note struct {
Url string
Title string
Date string
Body string
}
func loadNotes() ([]Note) {
session, err := mgo.Dial("localhost")
if err != nil {
panic(err)
}
defer session.Close()
// Optional. Switch the session to a monotonic behavior.
session.SetMode(mgo.Monotonic, true)
c := session.DB("test").C("notes")
notes := []Note{}
iter := c.Find(nil).Limit(100).Iter()
err = iter.All(¬es)
if err != nil {
panic(iter.Err())
}
return notes
}
func main() {
notes := loadNotes()
for note := range notes {
fmt.Println(note.Title)
}
}
If I just print out notes
I get what looks like a slice of two structs, but I can't access them by means of notes.Title
or anything like that.
[{ Some example title 20 September 2012 Some example content}]
This is what my documents look like:
> db.notes.find()
{ "_id" : "some-example-title", "title" : "Some example title", "date" : "20 September 2012", "body" : "Some example content" }
The real issue is that it's returning the notes as one big slice rather than a Note{}
(I think?)
If I'm doing something obviously wrong, any insight would help.
Solution
your problem is here:
for note := range notes {
fmt.Println(note.Title)
}
it should read:
for _, note := range notes {
fmt.Println(note.Title)
}
using a range statement on a slice returns pairs of the form i, v
, where i is the index in the slice, and v is the item at the index in that slice. Since you omitted the second value, you're looping on indexes, not on Note
values.
It's in the RangeClause section of the spec: http://golang.org/ref/spec#RangeClause
OTHER TIPS
It looks like it's working to me. notes is a slice of structs as you indicated.
for _, n := range notes {
n.Title // do something with title
n.Url // do something with url
}
or alternatively if you just want the first one:
notes[0].Title
should work as well.
A slice of structs can't be indexed as if it were a struct itself because it isn't a struct.
iter.All() retrieves the whole result set at once into a slice. If you just want one row, use iter.Next(). See https://groups.google.com/forum/#!msg/mgo-users/yUGZi70ik9Y/J8ktshJgF7QJ