Reputation: 77
I'm making a program in Golang using the flag package, and I'm trying to check if more than one flag in a specific list is true. Right now, this is my solution:
List := 0
if *md5flag {
List++
}
if *sha1flag {
List++
}
if *sha256flag {
List++
}
if *sha512flag {
List++
}
if List > 1 {
// Do stuff
os.Exit(1)
}
Would there be an easier way to do this, and by using a single if statement?
Upvotes: 3
Views: 5935
Reputation: 34252
If all you need is to check that at most one flag is set and exit immediately in that case, you can use a loop with short circuiting, though I'm not sure if it's more readable for just 4 values:
flags := []*bool{md5flag, sha1flag, sha256flag, sha512flag}
seenSetFlag := false
for _, f := range flags {
if *f {
if seenSetFlag {
os.Exit(1)
}
seenSetFlag = true
}
}
Upvotes: 4
Reputation: 44587
You can use a bitmask. But the bitmask approach is more effective if you set up your flags to be a bitmask to begin with, i.e. the flags should be integers that can be OR'ed together. bool
in Go doesn't support |
operator.
With a bitmask, to check if more than one bit is set you can use the trick x & (x - 1) != 0
. This checks if x
is a power of two, when it is not, more than one bit is set. (source)
type alg int
const (
md5flag alg = 1 << iota
sha1flag
sha256flag
sha512flag
)
func main() {
// clients can initialize the value with bitwise-OR
supportedAlgos := md5flag | sha256flag
// check if more than one is set
if supportedAlgos & (supportedAlgos - 1) != 0 {
// do stuff
}
}
If you can't refactor your code to use a bitmask you may still construct it from the individual bool pointers. But then the approach isn't much different than the one you have right now.
func toBitmask(bs ...*bool) int {
bitmask := 0
for i, b := range bs {
if b != nil && *b {
bitmask |= 1 << i
}
}
return bitmask
}
func main() {
list := toBitmask(md5flag, sha1flag, sha256flag, sha512flag)
if list & (list - 1) != 0 {
// do stuff
}
}
Playground: https://play.golang.org/p/PXK_1sS5ZxI
Upvotes: 0
Reputation: 12928
Go doesn't have any conversion from bool
to int
, so you need to use an if-statement in some way.
I would do something like this
package main
import (
"fmt"
)
func boolsToInt(flags... bool) int {
value := 0
for _, flag := range flags {
if flag {
value++
}
}
return value
}
func main() {
b1, b2, b3, b4 := false, true, true, false
fmt.Println(boolsToInt(b1, b2, b3, b4))
}
Upvotes: 0