I am trying to do a basic TODO list application in Go. I am creating the CRUD operations on my cluster from mongodb atlas. But I have a problem decoding BSON objects. For my model I use a struct which is unimported but it implements a interface which is used in the repo. When trying to read from database I get this error:
panic: no decoder found for interfaces.IToDoItem
I know I should somehow implement a decoder for my interface but can not realize how to do it, without exporting my main struct from model. That would also mean I won't have a privacy in the model and the items in the model can be accessed in any mode all around the program, a thing which I think is wrong.
Here is my code:
model.go
type toDoItem struct{
ItemId int `bson:"itemId,omitempty"`
Title string `bson:"title,omitempty"`
Description string `bson:"description,omitempty"`
}
func New(itemId int,title string,description string) interfaces.IToDoItem {
return toDoItem{
ItemId: itemId,
Title: title,
Description: description,
}
}
func (item toDoItem)GetItemId()int{
return item.ItemId
}
func (item toDoItem)GetTitle()string{
return item.Title
}
func (item toDoItem)GetDescription()string{
return item.Description
}
Interface
type IToDoItem interface {
GetItemId() int
GetTitle() string
GetDescription() string
}
repo function
func (r *Repository)GetAll() []interfaces.IToDoItem{
cursor, err := r.collection.Find(context.TODO(), bson.D{})
if err != nil{
panic(err)
}
defer cursor.Close(context.Background())
var allItems []interfaces.IToDoItem
for cursor.Next(context.Background()){
var result interfaces.IToDoItem
err := cursor.Decode(&result)
if err!= nil{
panic(err)
}
allItems = append(allItems[:],result)
}
fmt.Println(allItems)
return []interfaces.IToDoItem{}
}
For now it does not return anything because I want to resolve the issues at the repo level.
Interfaces are not concrete types, there may be multiple (any number of) types implementing it. The driver rightfully doesn't know how to instantiate it.
Fields of toDoItem
are exported, there is no reason to make toDoItem
itself unexported. Just export it and use a slice of []ToDoItem
(or []*ToDoItem
), and all your problems go away.
Also note that there is a Cursor.All()
method to get all results, so you don't have to iterate over the documents and call Cursor.Decode()
for each.
If you'd ever need to register custom decoders, check out this answer how to do it: