我正在学习Go中的一些基本概念,因此,我正在尝试进行类似于我在其他编程语言中所做的那样的数据层抽象,并且我的以下代码在以下错误中运行:
Failed to save task: datastore: invalid entity type
代码如下:
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())
}
非常感谢您向我解释为什么这不起作用。
我的第二个问题是,在官方datastore
Go package documentation中,它表示以下内容:
datastore
在应用程序中仅实例化一次// 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.
}
的推荐模式是什么?
dsClient
上的文档非常清楚:使用指定键将实体src保存到数据存储中。您既不传递结构指针也不传递src必须是结构指针或实现PropertyLoadSaver。
Client.Put()
。您传递一个指向接口类型的指针(如果经常使用,应该很少使用)。在Go中,接口有点像“包装器”类型,它可以包装具体的值及其类型,其中包装的值也可以是指针。因此,如果需要一个指针,则该指针将包裹在接口中,因此不需要使用指向接口本身的指针。在某些情况下,它仍然是必需的或有用的,但很少见。在您遇到需要之前,请避免使用它。例如,当您需要接口类型的反射类型描述符时,请参见Client.Put()
。由于将PropertyLoadSaver
用作how to append nil to dynamic type slice by reflect.Append(这是指向结构的指针),因此只需使用*Task
而不是entity
。
entity
在应用程序中仅实例化一次&entity
的推荐模式是什么?
一种方法是使用包级别(“全局”)变量,在其中存储一次创建的client.Put(ctx, entityKey, entity)
。无论何时需要dsClient
,只需引用此变量即可。