Golang | How would I check if multiple boolean values are true in a single if statement?

huangapple go评论76阅读模式
英文:

Golang | How would I check if multiple boolean values are true in a single if statement?

问题

我正在使用 Golang 的 flag 包编写一个程序,并尝试检查特定列表中是否有多个标志为 true。目前,这是我的解决方案:

List := 0

if *md5flag {
    List++
}
if *sha1flag {
    List++
}
if *sha256flag {
    List++
}
if *sha512flag {
    List++
}

if List > 1 {
    // 做一些操作
    os.Exit(1)
}

是否有更简单的方法来实现这个功能,并且只使用一个 if 语句呢?

英文:

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?

答案1

得分: 3

如果你只需要检查最多一个标志是否被设置,并在这种情况下立即退出,你可以使用带有短路的循环,尽管我不确定对于只有4个值来说是否更易读:

flags := []*bool{md5flag, sha1flag, sha256flag, sha512flag}
seenSetFlag := false
for _, f := range flags {
    if *f {
        if seenSetFlag {
            os.Exit(1)
        }
        seenSetFlag = true
    }
}
英文:

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

答案2

得分: 0

Go语言没有从boolint的直接转换,所以你需要以某种方式使用if语句。

我会这样做:

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))
}
英文:

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

答案3

得分: 0

你可以使用位掩码(bitmask)的方法。但是,如果你一开始就将标志设置为位掩码,即标志应该是可以进行按位或(|)操作的整数,那么位掩码的方法会更有效。Go中的bool类型不支持|运算符。

使用位掩码,要检查是否设置了多个位,你可以使用技巧x & (x - 1) != 0。这个技巧检查x是否是2的幂,当它不是时,表示设置了多个位。(来源:Stack Overflow

type alg int

const (
    md5flag alg = 1 << iota
    sha1flag 
    sha256flag
    sha512flag
)

func main() {
    // 客户端可以使用按位或进行初始化
    supportedAlgos := md5flag | sha256flag

    // 检查是否设置了多个位
    if supportedAlgos & (supportedAlgos - 1) != 0 {
        // 做一些操作
    }
}

如果你无法重构代码以使用位掩码,你仍然可以从单独的布尔指针构建它。但是,这种方法与你现在的方法并没有太大区别。

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 {
        // 做一些操作
    }
}

Playground: https://play.golang.org/p/PXK_1sS5ZxI

英文:

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 &amp; (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 &lt;&lt; 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 &amp; (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 &amp;&amp; *b {
            bitmask |= 1 &lt;&lt; i
        }
    }
    return bitmask
}

func main() {
    list := toBitmask(md5flag, sha1flag, sha256flag, sha512flag)

    if list &amp; (list - 1) != 0 {
        // do stuff
    }
}

Playground: https://play.golang.org/p/PXK_1sS5ZxI

huangapple
  • 本文由 发表于 2021年11月14日 20:45:16
  • 转载请务必保留本文链接:https://go.coder-hub.com/69963113.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定