I'm in the process of learning some basic concepts in Go and as such I'm experimenting with a data layer abstraction similar to what I would have done in other programming languages and I am running in the following error with my below code:
Failed to save task: datastore: invalid entity type
The code is the following:
package main
import (
"context"
"fmt"
"log"
"cloud.google.com/go/datastore"
"github.com/google/uuid"
)
type DatastoreEntity interface {
Kind() string
Name() string
}
type Task struct {
TaskId string
Description string
}
func (task *Task) Kind() string {
return "tasks"
}
func (task *Task) Name() string {
return task.TaskId
}
func main() {
task := Task{
TaskId: uuid.New().String(),
Description: "Buy milk",
}
SaveEntity(&task)
}
func SaveEntity(entity DatastoreEntity) {
ctx := context.Background()
projectId := "my-gcp-project"
client, err := datastore.NewClient(ctx, projectId)
if err != nil {
log.Fatalf("Failed to create client: %v", err)
}
entityKey := datastore.NameKey(entity.Kind(), entity.Name(), nil)
if _, err := client.Put(ctx, entityKey, &entity); err != nil {
log.Fatalf("Failed to save task: %v", err)
}
fmt.Printf("Saved %v: %v\n", entityKey, entity.Name())
}
Any help in explaining me why this doesn't work would be much appreciated.
My second question is that in the official datastore Go package documentation it says the following:
// Create a datastore client. In a typical application, you would create
// a single client which is reused for every datastore operation.
dsClient, err := datastore.NewClient(ctx, "my-project")
if err != nil {
// Handle error.
}
What is the recommended pattern to instantiate a dsClient only once in an application?
Client.Put(): "Put saves the entity src into the datastore with the given key. src must be a struct pointer or implement PropertyLoadSaver" You don't pass a struct pointer norPropertyLoadSaver. You pass a pointer to interface type (which you should rarely if ever use).client.Put(ctx, entityKey, &entity)toclient.Put(ctx, entityKey, entity)it actually works. Thanks! However, when you say "You pass a pointer to interface type (which you should rarely if ever use)" would you mind to elaborate why I should never do this?