3

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?

2
  • does go have multiple in sum/map functions? Something like [md5flag, sha1flag, sha256flag, sha512flag].sum { |f| f ? : 1: 0 } would be perfect Commented Nov 14, 2021 at 12:58
  • 1
    Do you really care how many flags are on? Or just if any of them are on? if *md5flag || *sha1flag || *sha256flag { ... }. Commented Nov 14, 2021 at 15:06

3 Answers 3

4

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 } } 
Sign up to request clarification or add additional context in comments.

Comments

0

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)) } 

Comments

0

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

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.