接口实体放入 Google Cloud Datastore 失败
Put into Google Cloud Datastore fails for interface entity
我正在学习 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中是这样说的:
// 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
一次的推荐模式是什么?
Client.Put()
上的文档非常清楚:
Put saves the entity src into the datastore with the given key. src must be a struct pointer or implement PropertyLoadSaver.
您既不传递结构指针也不传递 PropertyLoadSaver
。您传递一个指向接口类型的指针(如果使用的话,您应该很少使用)。在 Go 中,接口有点像 "wrapper" 类型,它可以包装一个具体的值及其类型,其中包装的值也可以是一个指针。所以如果需要一个指针,指针被包装在接口中,所以不需要使用指向接口本身的指针。在某些情况下,它仍然是必需的或有用的,但这种情况很少见。在你遇到需要它之前,避免它。一个例子可能是当你需要接口类型的反射类型描述符时,参见 .
由于您使用 *Task
作为 entity
(指向结构的指针),只需使用 entity
而不是 &entity
。
client.Put(ctx, entityKey, entity)
What is the recommended pattern to instantiate a dsClient
only once in an application?
一种方法是使用包级别 ("global") 变量,您可以在其中存储创建一次的 datastore.Client
。在任何需要 Client
的地方,只需引用此变量即可。
我正在学习 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中是这样说的:
// 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
一次的推荐模式是什么?
Client.Put()
上的文档非常清楚:
Put saves the entity src into the datastore with the given key. src must be a struct pointer or implement PropertyLoadSaver.
您既不传递结构指针也不传递 PropertyLoadSaver
。您传递一个指向接口类型的指针(如果使用的话,您应该很少使用)。在 Go 中,接口有点像 "wrapper" 类型,它可以包装一个具体的值及其类型,其中包装的值也可以是一个指针。所以如果需要一个指针,指针被包装在接口中,所以不需要使用指向接口本身的指针。在某些情况下,它仍然是必需的或有用的,但这种情况很少见。在你遇到需要它之前,避免它。一个例子可能是当你需要接口类型的反射类型描述符时,参见
由于您使用 *Task
作为 entity
(指向结构的指针),只需使用 entity
而不是 &entity
。
client.Put(ctx, entityKey, entity)
What is the recommended pattern to instantiate a
dsClient
only once in an application?
一种方法是使用包级别 ("global") 变量,您可以在其中存储创建一次的 datastore.Client
。在任何需要 Client
的地方,只需引用此变量即可。