Hi great Go community. Sorry it's a long question, but i would really appreciate some guidance.
Let's say i have two different objects,
browser and
executable that implement
ScanCleaner interface.
type ScanCleaner interface {
scan()
clean()
}
type browser struct {
Name string
}
type exe struct {
Size int
}
These two objects are different internally but they implement the same scan and clean methods. In general i don't need to know their internals. I have this instead;
var objects []ScanCleaner
I can iterate through the objects, scan and clean them. So far so good, but i want to decouple scan and clean processes. One can scan the system, get a report and later clean based on that report file. So that interface slice should be stored appropriately in a file and recovered later.
I encode the objects slice, and get a perfectly good json output.
Output: [{"Name":"chrome"},{"Name":"firefox"},{"Size":1234},{"Size":4321}]
The problem arises when i need to decode report file and recover the objects interface slice. Object types are completely lost.
My current solution is this; I encapsulate every object with a string that specifies it's type,
type detection struct {
Type string
Object ScanCleaner
}
and encode the slice of detection instead. The Type string is main.exe or main.browser obtained by fmt.Sprintf("%T", obj).
Output: [{"Type":"main.browser","Object":{"Name":"chrome"}},{"Type":"main.exe","Object":{"Size":1234}}]
Finally, i use a dispatch routine that recognizes objects type by Type string, decodes the object with the correct type, and calls it's clean method.
func cleanAll(jsn []byte) {
detects := []struct {
Type string
Object json.RawMessage
}{}
json.Unmarshal(jsn, &detects)
for _, d := range detects {
var sc ScanCleaner
switch d.Type {
case "main.exe":
var e exe
json.Unmarshal(d.Object, &e)
sc = e
case "main.browser":
var b browser
json.Unmarshal(d.Object, &b)
sc = b
}
sc.clean()
}
}
Output:
browser clean {chrome}
browser clean {firefox}
exe clean {1234}
exe clean {4321}
--------------------
This solution is obviously not good. If i change an objects name, i should change the Type string in switch. Also i need to rely on the string returned by fmt.Sprintf("%T").
Is there a better solution to accomplish this task?
Thanks.