英文:
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语言没有从bool
到int
的直接转换,所以你需要以某种方式使用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 & (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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论