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 vue3页面el-table页面数据过多
  • ¥100 vue3中融入gRPC-web
  • ¥15 kali环境运行volatility分析android内存文件,缺profile
  • ¥15 写uniapp时遇到的问题
  • ¥15 vs 2008 安装遇到问题
  • ¥15 matlab有限元法求解梁带有若干弹簧质量系统的固有频率
  • ¥15 找一个网络防御专家,外包的
  • ¥100 能不能让两张不同的图片md5值一样,(有尝)
  • ¥15 informer代码训练自己的数据集,改参数怎么改
  • ¥15 请看一下,学校实验要求,我需要具体代码