Восстановите структуру, которая удовлетворяет определенному интерфейсу из строки JSON - PullRequest
0 голосов
/ 30 июня 2018

Я выполняю программу опроса задач (восстановление незавершенной задачи из базы данных).

Задача должна удовлетворять определенному Task интерфейсу:

type Task interface {
    // Identifier returns a unique string of a task
    Identifier() string
    // Data should be persistent
    Data() interface{}
    // Execute a task
    Execute()
}

Данные, хранящиеся в базе данных, удовлетворяют следующей структуре:

type Record struct {
    Identifier string      `json:"identifier"`
    Data       interface{} `json:"data"`
}

Когда запускается опросщик задач, он считывает сохраненные данные из базы данных, а затем (давайте просто пока проигнорируем обработку ошибок):

r := &Record{}
result := database.Get(key)
json.Unmarshal([]byte(result), r)

мы восстановили сохраненные данные из базы данных в r.

Появляется проблема, что я не могу вызвать метод Execute(), потому что r.Data на самом деле является типом interface{} (точнее, map[string]interface{}), отличным от типа Task.

Как я могу преобразовать или преобразовать r.Data в структуру, которая удовлетворяет интерфейсу Task, чтобы я мог успешно вызвать метод Execute()?

1 Ответ

0 голосов
/ 01 июля 2018

r.Data на самом деле тип interface{} (map[string]interface{} более конкретно).

Вам нужен набор методов, который удовлетворяет интерфейсу Task. Например,

package main

import "fmt"

type Task interface {
    // Identifier returns a unique string of a task
    Identifier() string
    // Data should be persistent
    Data() interface{}
    // Execute a task
    Execute()
}

type Record struct {
    Identifier string      `json:"identifier"`
    Data       interface{} `json:"data"`
}

type Data map[string]interface{}

// Task interface methods
func (d Data) Identifier() string { return "" }
func (d Data) Data() interface{}  { return nil }
func (d Data) Execute()           { fmt.Println("Execute()") }

func main() {
    r := Record{Data: map[string]interface{}{}}
    fmt.Printf("r.Data: %[1]T %[1]v\n", r.Data)
    if m, ok := r.Data.(map[string]interface{}); ok {
        r.Data = Data(m)
    }

    var tasks []Task
    if task, ok := r.Data.(Task); ok {
        tasks = append(tasks, task)
    }

    for _, task := range tasks {
        fmt.Printf("%T: ", task)
        task.Execute()
    }
}

Детская площадка: https://play.golang.org/p/SC9Ff8e-_pP

Выход:

r.Data: map[string]interface {} map[]
main.Data: Execute()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...