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?
r.Data
is actually type ofinterface{}
(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()