HiveBrain v1.2.0
Get Started
← Back to all entries
patterngoMinor

Map strings to (const) ints

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
mapstringsconstints

Problem

I'm imagining go generate would be a good tool for this. I want to convert strings to ints to save space.

type Source int

func NewSource(s string) Source {
    switch s {
    case "Twitter":
        return Twitter
    case "Facebook":
        return Facebook
    case "Gplus":
        return Gplus
    case "Spotify":
        return Spotify
    case "Linkedin":
        return Linkedin
    case "Github":
        return Github
    case "Lastfm":
        return Lastfm
    default:
        panic(ErrUnknownSourceType)
    }
}

const (
    Twitter Source = iota
    Facebook
    Gplus
    Spotify
    Linkedin
    Github
    Lastfm
)

Solution

Shortest (shortest by you) would be indeed to use go generate. If you don't want to do that:

You have to enumerate your source names and source values to associate them, you can't avoid that.

But this enumeration and pairing can be shorter by using a map[string]Source:

var srcMap = map[string]Source{
    "Twitter":  Twitter,
    "Facebook": Facebook,
    "Gplus":    Gplus,
    "Spotify":  Spotify,
    "Linkedin": Linkedin,
    "Github":   Github,
    "Lastfm":   Lastfm,
}

func NewSource(s string) Source {
    if src, ok := srcMap[s]; ok {
        return src
    }
    panic(ErrUnknownSourceType)
}


Also note that panicing is a little "strong" reaction for an invalid source name. I would rather return an error along with the source, or return a special UnknownSrc source instead of panicing.

And while we're at it: you should exploit the zero value of Source for representing UnknownSrc and that way you don't even have to use the comma-ok idiom when checking in the map: indexing a map returns the zero value of the value type if the key is not found.

So:

const (
    UnknownSrc Source = iota // It will be 0, zero value for the underlying type (int)
    Twitter
    // ... and your other sources
)


And this way converting a source name to the Source type is one-line:

func NewSource(s string) Source {
    return srcMap[s]
}


It's just indexing a map, you don't even need a function for that.

If you would want to return an error, it could look like this:

func NewSource(s string) (Source, error) {
    if src, ok := srcMap[s]; ok {
        return src, nil
    }
    return UnknownSrc, errors.New("Invalid Source name!") 
}

Code Snippets

var srcMap = map[string]Source{
    "Twitter":  Twitter,
    "Facebook": Facebook,
    "Gplus":    Gplus,
    "Spotify":  Spotify,
    "Linkedin": Linkedin,
    "Github":   Github,
    "Lastfm":   Lastfm,
}

func NewSource(s string) Source {
    if src, ok := srcMap[s]; ok {
        return src
    }
    panic(ErrUnknownSourceType)
}
const (
    UnknownSrc Source = iota // It will be 0, zero value for the underlying type (int)
    Twitter
    // ... and your other sources
)
func NewSource(s string) Source {
    return srcMap[s]
}
func NewSource(s string) (Source, error) {
    if src, ok := srcMap[s]; ok {
        return src, nil
    }
    return UnknownSrc, errors.New("Invalid Source name!") 
}

Context

StackExchange Code Review Q#100907, answer score: 5

Revisions (0)

No revisions yet.