Golang 中的位掩码和位操作
Bitmasking and Bitwise Operations in Golang
我是一般编程的初学者,所以如果我在提出这个问题时犯了一些错误,我很抱歉。
我正在学习的教程介绍了这段代码:
package main
import (
"fmt"
)
const (
isAdmin = 1 << iota
isHeadquarters
canSeeFinancials
canSeeAfrica
canSeeAsia
canSeeEurope
canSeeNorthAmerica
canSeeSouthAmerica
)
func main() {
var roles byte = isAdmin | canSeeFinancials | canSeeEurope
fmt.Printf ("%b\n", roles)
fmt.Printf ("Is Admin? %v\n", isAdmin & roles == isAdmin)
}
教程中的人很快提到了这部分的名称 Bitmasking。
fmt.Printf ("Is Admin? %v\n", isAdmin & roles == isAdmin)
现在,据我了解,这里发生的过程是这样的:
正在询问计算机 isAdmin 和 roles 是否等于 isAdmin 并回复 真.
但是,当我尝试这样做时:
fmt.Printf ("Is Admin? %v\n", roles == isAdmin)
结果为 false。
有人可以更详细地说明这个过程背后的整个逻辑吗?这一点让我有点困惑,我想知道为什么会这样。谢谢。
您所有的角色常量都是特殊数字,其中二进制(2 的补码)表示恰好包含一个 1
位,所有其他位均为零,并且它们都不同(1
位在每一个中都处于不同的位置)。这是通过将 1
数字向左移动并增加值 (iota
) 来实现的。
role
变量的值是使用按位或构造的:
var roles byte = isAdmin | canSeeFinancials | canSeeEurope
按位或保留 1
位,结果将只有 0
位,其中每个操作数在该位置包含 0
。由于所有被 OR 运算的值都在不同位置包含一个 1
位,因此 role
将包含与 OR 运算的不同角色一样多的位,并且在它们的特殊位置。
为了便于理解这些位,让我们打印二进制表示:
fmt.Printf("isAdmin %08b\n", isAdmin)
fmt.Printf("canSeeFinancials %08b\n", canSeeFinancials)
fmt.Printf("canSeeEurope %08b\n", canSeeEurope)
fmt.Printf("-------------------------\n")
fmt.Printf("roles %08b\n", roles)
这将输出:
isAdmin 00000001
canSeeFinancials 00000100
canSeeEurope 00100000
-------------------------
roles 00100101
如您所见,roles
包含 1
s,其中任何上述位模式都具有 1
.
当您使用按位与(掩码)时,如果给定位置的任何输入位为 0
,则结果位将为 0
,并且仅为 1
如果两个位都是 1
s.
表达式:
isAdmin & roles
因为 isAdmin
包含一个 1
位,上面的掩码将是一个最多也可以包含一个 1
位的数字,前提是 roles
在那个位置有一个 1
位。实际上,此掩码告诉 roles
是否包含 isAdmin
位。如果它包含它,结果将是一个等于 isAdmin
的值。如果不是,结果将是一个包含所有 0
位的数字,即:十进制 0
.
再次可视化位:
fmt.Printf("roles %08b\n", roles)
fmt.Printf("isAdmin %08b\n", isAdmin)
fmt.Printf("-------------------------\n")
fmt.Printf("isAdmin & roles %08b\n", isAdmin&roles)
输出:
roles 00100101
isAdmin 00000001
-------------------------
isAdmin & roles 00000001
尝试 Go Playground 上的示例。
所以表达式:
isAdmin & roles == isAdmin
如果 roles
包含(包括)isAdmin
角色,将是 true
,否则 false
。
无掩码:
roles == isAdmin
这将是 true
如果 roles
等于 isAdmin
,也就是说,如果它只包含 isAdmin
角色和 nothing 否则。如果包含其他角色,显然不会等于isAdmin
.
我是一般编程的初学者,所以如果我在提出这个问题时犯了一些错误,我很抱歉。
我正在学习的教程介绍了这段代码:
package main
import (
"fmt"
)
const (
isAdmin = 1 << iota
isHeadquarters
canSeeFinancials
canSeeAfrica
canSeeAsia
canSeeEurope
canSeeNorthAmerica
canSeeSouthAmerica
)
func main() {
var roles byte = isAdmin | canSeeFinancials | canSeeEurope
fmt.Printf ("%b\n", roles)
fmt.Printf ("Is Admin? %v\n", isAdmin & roles == isAdmin)
}
教程中的人很快提到了这部分的名称 Bitmasking。
fmt.Printf ("Is Admin? %v\n", isAdmin & roles == isAdmin)
现在,据我了解,这里发生的过程是这样的: 正在询问计算机 isAdmin 和 roles 是否等于 isAdmin 并回复 真.
但是,当我尝试这样做时:
fmt.Printf ("Is Admin? %v\n", roles == isAdmin)
结果为 false。
有人可以更详细地说明这个过程背后的整个逻辑吗?这一点让我有点困惑,我想知道为什么会这样。谢谢。
您所有的角色常量都是特殊数字,其中二进制(2 的补码)表示恰好包含一个 1
位,所有其他位均为零,并且它们都不同(1
位在每一个中都处于不同的位置)。这是通过将 1
数字向左移动并增加值 (iota
) 来实现的。
role
变量的值是使用按位或构造的:
var roles byte = isAdmin | canSeeFinancials | canSeeEurope
按位或保留 1
位,结果将只有 0
位,其中每个操作数在该位置包含 0
。由于所有被 OR 运算的值都在不同位置包含一个 1
位,因此 role
将包含与 OR 运算的不同角色一样多的位,并且在它们的特殊位置。
为了便于理解这些位,让我们打印二进制表示:
fmt.Printf("isAdmin %08b\n", isAdmin)
fmt.Printf("canSeeFinancials %08b\n", canSeeFinancials)
fmt.Printf("canSeeEurope %08b\n", canSeeEurope)
fmt.Printf("-------------------------\n")
fmt.Printf("roles %08b\n", roles)
这将输出:
isAdmin 00000001
canSeeFinancials 00000100
canSeeEurope 00100000
-------------------------
roles 00100101
如您所见,roles
包含 1
s,其中任何上述位模式都具有 1
.
当您使用按位与(掩码)时,如果给定位置的任何输入位为 0
,则结果位将为 0
,并且仅为 1
如果两个位都是 1
s.
表达式:
isAdmin & roles
因为 isAdmin
包含一个 1
位,上面的掩码将是一个最多也可以包含一个 1
位的数字,前提是 roles
在那个位置有一个 1
位。实际上,此掩码告诉 roles
是否包含 isAdmin
位。如果它包含它,结果将是一个等于 isAdmin
的值。如果不是,结果将是一个包含所有 0
位的数字,即:十进制 0
.
再次可视化位:
fmt.Printf("roles %08b\n", roles)
fmt.Printf("isAdmin %08b\n", isAdmin)
fmt.Printf("-------------------------\n")
fmt.Printf("isAdmin & roles %08b\n", isAdmin&roles)
输出:
roles 00100101
isAdmin 00000001
-------------------------
isAdmin & roles 00000001
尝试 Go Playground 上的示例。
所以表达式:
isAdmin & roles == isAdmin
如果 roles
包含(包括)isAdmin
角色,将是 true
,否则 false
。
无掩码:
roles == isAdmin
这将是 true
如果 roles
等于 isAdmin
,也就是说,如果它只包含 isAdmin
角色和 nothing 否则。如果包含其他角色,显然不会等于isAdmin
.