On Mon, Feb 19, 2018 at 4:45 PM, Doğan Kurt <kultigin....@gmail.com> wrote:
> 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.
>
> Here is the working code: https://play.golang.org/p/cYgnhgxkPL0
>
> 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.


You can use an intermediate structure to parse the JSON input, and
then process that to construct the slice:

var entry []struct {
    Name string
    Size int
    ..
}

json.Unmarshal(&entry)
for _,e:=range entry {
    if len(e.Name)==0 {
        ... // This entry has size, create struct exe
    } else {
        ... // This entry has name, create struct Browser
    }
}

Of course, this assumes you can deduce the type of the element based
on its contents easily.


>
> 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).
>
> Here is a working code: https://play.golang.org/p/KeJjl8IOqRP
>
> 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()
> }
> }
>
> Here is the final working code: https://play.golang.org/p/HpHFiHrT2oz
>
> 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.
>
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts+unsubscr...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

-- 
You received this message because you are subscribed to the Google Groups 
"golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to golang-nuts+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to