3

I have a struct as follows:

type MyStruct struct {
   Part1 string
   Part2 string
   Part3 string
}

I have a string separated by slashes that I want to map to this:

part1/part2/part3

However, the string may only contain 1 part such as part1 or two parts such as part1/part2

if any part is missing it much be mapped as an empty string.

I am very new to go so wondering what the best way to achieve this is. Typically i would split the string and check the length to know what to do. In go is there a more elegant way to do this?

4 Answers 4

4

Here's a version of peterSO's solution that uses a wrapper to help simplify the logic.

package main

import (
    "fmt"
    "strings"
)

type Wrap []string

func (w Wrap) Get(i int) string {
    if 0 <= i && i < len(w) {
        return w[i]
    }
    return ""
}

type MyStruct struct {
    Part1 string
    Part2 string
    Part3 string
}

func main() {
    str := "part1/part2/part3"
    split := Wrap(strings.Split(str, "/"))
    var parts MyStruct
    parts.Part1 = split.Get(0)
    parts.Part2 = split.Get(1)
    parts.Part3 = split.Get(2)
    fmt.Println(parts)

    str = "part1/part2"
    split = Wrap(strings.Split(str, "/"))
    parts = MyStruct{}
    parts.Part1 = split.Get(0)
    parts.Part2 = split.Get(1)
    parts.Part3 = split.Get(2)
    fmt.Println(parts)
}
Sign up to request clarification or add additional context in comments.

Comments

4
package main

import (
    "fmt"
    "strings"
)

type MyStruct struct {
    Part1 string
    Part2 string
    Part3 string
}

func (m *MyStruct) set(s string) *MyStruct {
    p := []*string{&m.Part1, &m.Part2, &m.Part3}
    for i, v := range strings.Split(s+"//", "/")[:3] {
        *p[i] = v
    }
    return m
}

func main() {
    var v MyStruct
    fmt.Printf("%#v\n", v.set("foo"))
    fmt.Printf("%#v\n", v.set(""))
    fmt.Printf("%#v\n", v.set("bar/baz"))
    fmt.Printf("%#v\n", v.set("alpha//omega"))
    fmt.Printf("%#v\n", v.set("/var/mail"))
}

Playground


Output:

&main.MyStruct{Part1:"foo", Part2:"", Part3:""}
&main.MyStruct{Part1:"", Part2:"", Part3:""}
&main.MyStruct{Part1:"bar", Part2:"baz", Part3:""}
&main.MyStruct{Part1:"alpha", Part2:"", Part3:"omega"}
&main.MyStruct{Part1:"", Part2:"var", Part3:"mail"}

Comments

1

For example,

package main

import (
    "fmt"
    "strings"
)

type MyStruct struct {
    Part1 string
    Part2 string
    Part3 string
}

func main() {
    str := "part1/part2/part3"
    split := strings.Split(str, "/")
    var parts MyStruct
    if len(split) > 0 {
        parts.Part1 = split[0]
        if len(split) > 1 {
            parts.Part2 = split[1]
            if len(split) > 2 {
                parts.Part3 = split[2]
            }
        }
    }
    fmt.Println(parts)
}

Output:

{part1 part2 part3}

1 Comment

Is it not possible to check if the element exists such as if split[0] { // do something here }
0

Expanding on dyoo's answer with shorter syntax and renamed types as I bypassed it for these two reasons, however it is the most extensible and reliable solution. The real benefit comes if you need to change from 3 to n elements, all that is required is a change to your struct definition and initialisation. StrSlice type is also very reusable when ever default values are required for a slice of strings.

package main

import (
    "fmt"
    "strings"
)

type MyStruct struct {
    Part1 string
    Part2 string
    Part3 string
}

type StrSlice []string

func (s StrSlice) Get(i int) string {
    if i >= 0 && i < len(s) {
        return s[i]
    }
    return ""
}

func main() {

    str := "part1/part2/part3"
    slice := StrSlice(strings.Split(str, "/"))
    parts := MyStruct{slice.Get(0),slice.Get(1),slice.Get(2)}
    fmt.Println(parts)

}

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.