pointers - 将接口(interface)实体放入 Google Cloud Datastore 失败

标签 pointers go google-cloud-platform interface google-cloud-datastore

我正在学习 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 .您传递一个指向接口(interface)类型的指针(如果曾经使用过,您应该很少使用)。在 Go 中,接口(interface)有点像“包装器”类型,它可以包装一个具体的值及其类型,其中包装的值也可能是一个指针。因此,如果需要指针,则指针被包装在接口(interface)中,因此不需要使用指向接口(interface)本身的指针。在某些情况下,它仍然是必需的或有用的,但很少见。在你遇到对它的需要之前,避免它。例如,当您需要接口(interface)类型的反射类型描述符时,请参阅 how to append nil to dynamic type slice by reflect.Append .

由于您使用 *Task作为您的entity (这是一个指向结构的指针),只需使用 entity而不是 &entity .
client.Put(ctx, entityKey, entity)

What is the recommended pattern to instantiate a dsClient only once in an application?



一种方法是使用包级别(“全局”)变量来存储 datastore.Client。创建一次。无论您在哪里需要 Client , 只引用这个变量。

关于pointers - 将接口(interface)实体放入 Google Cloud Datastore 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59808502/

相关文章:

c - 从不兼容的指针类型 C 返回

c - 使用 Park&Miller RNG 制作大样本?

dictionary - 如何在 Go 的映射中分配结构字段

json - 忽略 JSON Marshal 上不支持的类型错误

google-cloud-platform - 如何减少谷歌数据流作业中的初始化和终止时间?

android - 错误 : OAuth2Credentials instance does not support refreshing the access token. 如何使用 token 值字符串创建 AccessToken 实例?

c - 删除链表的第一个节点

没有指针或引用的c++虚函数调用

Goland 看不到来自另一个文件的函数

mysql - 由于循环引用,如何在迁移到 google cloud sql 时禁用外键检查