Не удалось вставить в Google Cloud Datastore для объекта интерфейса - PullRequest
1 голос
/ 19 января 2020

Я нахожусь в процессе изучения некоторых базовых c концепций в 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 документации пакета говорится следующее:

// 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 только один раз в приложении?

1 Ответ

3 голосов
/ 19 января 2020

do c довольно ясно для Client.Put():

Put сохраняет сущность sr c в хранилище данных с заданным ключом. sr c должен быть указателем структуры или реализовывать PropertyLoadSaver.

Вы не передаете указатель структуры или PropertyLoadSaver. Вы передаете указатель на тип интерфейса (который вы должны использовать редко, если когда-либо). В Go интерфейс подобен типу «обертки», он может переносить конкретное значение и его тип, где перенесенное значение также может быть указателем. Поэтому, если указатель необходим, указатель помещается в интерфейс, поэтому нет необходимости использовать указатель на сам интерфейс. В некоторых случаях это все еще требуется или полезно, но это редко. Пока вы не столкнетесь с необходимостью, избегайте этого. Примером может быть случай, когда вам нужен дескриптор типа отражателя типа интерфейса, см. Как добавить nil к динамическому срезу типа c с помощью отражателя. Приложение .

Поскольку вы используете *Task в качестве entity (который является указателем на структуру), просто используйте entity вместо &entity.

client.Put(ctx, entityKey, entity)

Каков рекомендуемый шаблон для создания экземпляра только dsClient один раз в приложении?

Один из способов сделать это - использовать переменную уровня пакета ("global"), где вы храните datastore.Client, созданный один раз. Везде, где вам нужен Client, просто обратитесь к этой переменной.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...