dongshungou7699 2018-06-30 19:05
浏览 41
已采纳

从JSON字符串还原满足定义的接口的结构

I am implementing a task poller (restore unfinished task from a database).

The task must satisfy a defined Task interface:

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

The data stored in database satisfy the following struct:

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

When task poller starts, it read the stored data from the database, then (let's just ignore error handling for now):

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

we restored the saved data from the database into r.

A problem appears that I cannot call the Execute() method because r.Data is actually type of interface{} (map[string]interface{} more specifically ) other than type of Task.

How can I convert or transform the r.Data to become a struct that satisfies Task interface so that I can successfully call Execute() method?

  • 写回答

1条回答 默认 最新

  • dqqxkq4047 2018-06-30 21:14
    关注

    r.Data is actually type of interface{} (map[string]interface{} more specifically).

    You need a method set that satisfies the Task interface. For example,

    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
    ", 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()
        }
    }
    

    Playground: https://play.golang.org/p/SC9Ff8e-_pP

    Output:

    r.Data: map[string]interface {} map[]
    main.Data: Execute()
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 我的R语言提示去除连锁不平衡时clump_data报错,图片以下所示,卡了好几天了,苦恼不知道如何解决,有人帮我看看怎么解决吗?
  • ¥15 在获取boss直聘的聊天的时候只能获取到前40条聊天数据
  • ¥20 关于URL获取的参数,无法执行二选一查询
  • ¥15 液位控制,当液位超过高限时常开触点59闭合,直到液位低于低限时,断开
  • ¥15 marlin编译错误,如何解决?
  • ¥15 有偿四位数,节约算法和扫描算法
  • ¥15 VUE项目怎么运行,系统打不开
  • ¥50 pointpillars等目标检测算法怎么融合注意力机制
  • ¥20 Vs code Mac系统 PHP Debug调试环境配置
  • ¥60 大一项目课,微信小程序