2
\$\begingroup\$

I have two code snippets, doing exactly the same thing and both get the job done:

  1. use defaults
  2. use from config

Which is cleaner to use in golang and why?

first option:


package main

import (
    "fmt"
    "strings"
)

func main() {
    fmt.Println(getShCfg(Cfg{}), "\n================")
    fmt.Println(getShCfg(Cfg{"8MB", "4MB"}), "\n================")
    fmt.Println(getShCfg(Cfg{"8MB", ""}), "\n================")
    fmt.Println(getShCfg(Cfg{"", "4MB"}), "\n================")
}

type Cfg struct { A, B string }

func getShCfg(c Cfg) string {
    var out []string

    la := "l_sh_dit conf_data 7MB"
    lb := "l_sh_dit cert_data 3MB"

    if len(c.A) > 0 {
        out = append(out, "l_sh_dit conf_data " + c.A)
    } else {
        out = append(out, la)
    }
    if len(c.B) > 0 {
        out = append(out, "l_sh_dit cert_data "+c.B)

    } else {
        out = append(out, lb)
    }

    return strings.Join(out, ";\n\r") + ";"

}

second option:


package main

import (
    "fmt"
    "strings"
)

func main() {
    fmt.Println(getShCfg(Cfg{}), "\n================")
    fmt.Println(getShCfg(Cfg{"8MB", "4MB"}), "\n================")
    fmt.Println(getShCfg(Cfg{"8MB", ""}), "\n================")
    fmt.Println(getShCfg(Cfg{"", "4MB"}), "\n================")
}

type Cfg struct { A, B string }

func getShCfg(c Cfg) string {
    out := []string{
        getCfgProp("l_sh_dit conf_data", c.A, "7MB"),
        getCfgProp("l_sh_dit cert_data", c.B, "3MB"),
    }
    return strings.Join(out, ";\n\r") + ";"

}

func getCfgProp(key, val, def string) string {
    if len(val) > 0 {
        return key + " " + val
    }
    return key + " " + def
}


I would prefer the second option as it is more scalable i.e. if there are more than 2 parameters (two if else) so in this case I'm skipping on another if-else in the code …

But in case there are only 2 parameters, is it worth to create a helper function?

Also if there is a better/cleaner approach to achieve it with Golang please let me know

\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

None of the above. Rewrite the first option in readable form. For example,

package main

import (
    "fmt"
    "strings"
)

type Cfg struct{ A, B string }

func getShCfg(c Cfg) string {
    var out []string

    msg := "l_sh_dit conf_data "
    if len(c.A) > 0 {
        msg += c.A
    } else {
        msg += "7MB"
    }
    out = append(out, msg)

    msg = "l_sh_dit cert_data "
    if len(c.B) > 0 {
        msg += c.B
    } else {
        msg += "3MB"
    }
    out = append(out, msg)

    return strings.Join(out, ";\n\r") + ";"
}

func main() {
    sep := "\n================"
    for _, cfg := range []Cfg{
        {},
        {"8MB", "4MB"},
        {"8MB", ""},
        {"", "4MB"},
    } {
        fmt.Println(getShCfg(cfg), sep)
    }
}

Output:

l_sh_dit conf_data 7MB;
l_sh_dit cert_data 3MB; 
================
l_sh_dit conf_data 8MB;
l_sh_dit cert_data 4MB; 
================
l_sh_dit conf_data 8MB;
l_sh_dit cert_data 3MB; 
================
l_sh_dit conf_data 7MB;
l_sh_dit cert_data 4MB; 
================

Factoring out common code and data simplifies and highlights the structure of the problem.

To generalize we typically need three to seven cases. We have two. Configuration parameters usually contain a wide range of information and data types and structures. Idle speculation is not useful.

We have safely encapsulated the problem. As we learn more, we can easily revise the code.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.