Search code examples
gostructconfig

Problem using go-ini's mapTo function with embedded struct


I'm new to Golang, so I think I'm doing something wrong using go-ini library to read a config file and map it to an embedded struct. I didn't find any working example searching on google, so I would be very happy to get some help here.

My test program works if I use the type "EmbeddedTestData" as a parameter in the "mapTo" call, but if I use the type "TestData" which contains the embedded type, the variable "data" is empty at the end.

/*
config.ini contains following example data:

[clientServer]
Port = ":1111"
WsPath = "/ws"

[courtServer]
port = ":2222"
wsPath = "/cs"
*/

package main

import (
    "fmt"
    "github.com/go-ini/ini"
    "os"
)

type TestData struct {
    EmbeddedTestData
}

type EmbeddedTestData struct {
    Port   string
    WsPath string
}

func main() {
    // load ini-file

    inidata, err := ini.Load("config.ini")

    if err != nil {
        fmt.Printf("Fail to read file: %v", err)
        os.Exit(1)
    }
    // data := new(EmbeddedTestData) -> this works fine!
    data := new(TestData) // doesn't work -> Content in variable 'data':  &{{ }}
    err = inidata.Section("clientServer").MapTo(data)
    fmt.Println("Content in variable 'data': ", data)
}

I would expect that variable "data" in the end contains the mapped data for Port/WsPath from the corresponding section in the config file in case I use type "TestData".


Solution

  • I am a new Golang learner too but i find a fix for your code the first problem in your code is

    type TestData struct {
        EmbeddedTestData
    }
    

    To define a struct you should use

    type <name> struct {
     // field1 type
     // field2 type
     // field3 type
     // ...
    }
    

    but you don't give a name to your type

    so let's change it and give it a name so we can access the EmbeddedTestData struct within the TestData struct

    we give it a name like d so we have

    type TestData struct {
        d EmbeddedTestData
    }
    

    now if we change the line from

    err = inidata.Section("clientServer").MapTo(data)
    

    to

    err = inidata.Section("clientServer").MapTo(data.d)
    

    to point to the EmbeddedTestData struct within the TestData struct and run the code again we get same output

    but when we print the err from

    err=inidata.Section("clientServer").MapTo(data.d)
    

    we get

    not a pointer to a struct

    if we add a & to our code to point the EmbeddedTestData struct it should work

    so the final code looks like this

    /*
    config.ini contains following example data:
    
    [clientServer]
    Port = ":1111"
    WsPath = "/ws"
    
    [courtServer]
    port = ":2222"
    wsPath = "/cs"
    */
    
    package main
    
    import (
        "fmt"
        "os"
    
        "github.com/go-ini/ini"
    )
    
    type TestData struct {
        d EmbeddedTestData
    }
    
    type EmbeddedTestData struct {
        Port   string
        WsPath string
    }
    
    func main() {
        // load ini-file
    
        inidata, err := ini.Load("config.ini")
    
        if err != nil {
            fmt.Printf("Fail to read file: %v", err)
            os.Exit(1)
        }
        
        data := new(TestData)
        err = inidata.Section("clientServer").MapTo(&data.d)
        fmt.Println("Content in variable 'data': ", data)
    }