Does Go have something similar to Python's in
keyword? I want to check if a value is in a list.
For example in Python:
x = 'red'
if x in ['red', 'green', 'yellow', 'blue']:
print "found"
else:
print "not found"
In Go I've come up with using the set idiom but I don't think it's ideal as I have to specify a int value that I'm not using.
x := "red"
valid := map[string]int{"red": 0, "green": 0,"yellow": 0, "blue": 0}
if _, ok := valid[x]; ok {
fmt.Println("found")
} else {
fmt.Println("not found")
}
I understand having an in
keyword is probably related to generics. Is there a way to do this using go generate or something?
You can use a map[string]bool
as a set. When testing and a key is not in the map, the zero value for bool
is returned which is false
.
So fill the map with the valid values as keys and true
as value. If a tested key-value is in the map, its stored true
value will be the result. If a tested key-value is not in the map, the zero value for the value type is returned which is false
.
Using this, the test becomes this simple:
valid := map[string]bool{"red": true, "green": true, "yellow": true, "blue": true}
if valid[x] {
fmt.Println("found")
} else {
fmt.Println("not found")
}
Try it on the Go Playground (with the variants mentioned below).
This is mentioned in the blog post: Go maps in action: Exploiting zero values
Note:
If you have many valid values, since all the values to be stored in the map are true
, it may be more compact to use a slice to list the valid values and use a for range
loop to initialize your map, something like this:
for _, v := range []string{"red", "green", "yellow", "blue"} {
valid[v] = true
}
Note #2:
If you don't want to go with the for range
loop initialization, you can still optimize it a little by creating an untyped (or bool
-typed) one-letter const
:
const t = true
valid := map[string]bool{"red": t, "green": t, "yellow": t, "blue": t}