Go语言中你所不知道的位操作用法

时间:2021-05-22

前言

因为之前一直忽略的就是所有语言中关于位操作,觉得用处并不多,可能用到也非常简单的用法,但是其实一直忽略的是它们的用处还是非常大的,下面先回顾一下位操作符的基础

位操作符

与操作:&

1 & 1 = 1

1 & 0 = 0

0 & 1 = 0

0 & 0 = 0

或操作:!

1 | 1 = 1

1 | 0 = 1

0 | 1 = 1

0 & 0 = 0

异或:^

1 ^ 1 = 0

1 ^ 0 = 1

0 ^ 1 = 1

0 ^ 0 = 0

左移:<<

1 << 10 = 1024

1 << 20 = 1M

1 << 30 = 1G

右移:>>

1024 >> 10 = 1

1024 >>1 = 512

1024 >>2 = 256

关于上述知识的一个应用实例

可能这个例子在实际中用并不是特别严谨,但是也提供了我们写代码的一种思路

这里拿微博或者qq用户的特权为例子:

一个qq号可以用VIP会员,SVIP超级会员,蓝钻用户,黄钻用户,红钻用户....

我们通常的想法可能是如果数据库中存储自己会给用户存这个字段表示这个用户开通了哪些特权

我们在代码中的写法可能也是如下所示:

package mainimport ( "fmt")type users struct { name string flag uint8 vip bool svip bool blue bool red bool yellow bool}func setVip(user users) users { user.vip = true return user}func isVip(user users) { if user.vip { fmt.Println("user is vip") } else { fmt.Println("user is not vip") }}func binaryTest() { var user users user.name = "test01" user.vip = true isVip(user) user.vip = false isVip(user)}func main() { binaryTest()}

这种实现方式也可以,但是明显我们需要为每个类型都做操作,并且如果以后又有更多的各种各样的会员和钻有需要添加新的,所以并不是最佳方法,下面我们通过位操作来实现上述的功能,代码如下:

package mainimport ( "fmt")type users struct { name string flag uint8}// 这里通过位移的方式默认00000 从左边一次为vip,svip,blue,red,yellowconst ( vip = 1 svip = (1 << 1) blue = (1 << 2) red = (1 << 3) yello = (1 << 4))// setFlag 用于设置用户开通了哪些特权func setFlag(user users, isSet bool, typeFlag uint8) users { if isSet == true { user.flag = user.flag | typeFlag } else { user.flag = user.flag ^ typeFlag } return user}//isFlag 用于判断用户是否开通某项特权func isFlag(user users, typeFlag uint8) bool { result := user.flag & typeFlag return result == typeFlag}func binaryTest() { var user users user.name = "coder" user.flag = 0 //判断用户是否是vip result := isFlag(user, vip) fmt.Printf("user is Vip:%t\n", result) //给用户开通vip,并看用户是否开通vip user = setFlag(user, true, vip) result = isFlag(user, vip) fmt.Printf("user is Vip:%t\n", result) //取消用户的vip,并查看用户是否还是vip user = setFlag(user, false, vip) result = isFlag(user, vip) fmt.Printf("user is Vip:%t\n", result)}func main() { binaryTest()}

上面代码就是一种位运算一种非常巧妙的用法,当新添加各种特权的时候只需要在最开始定义的常亮那里添加一行代码即可,就可以直接实现对这种特权的设置和取消,以及查看是否开通。

附常见的>>右移 <<左移 感觉右移左移应该也是非常常见的使用了

继续看例子:

package mainimport "fmt"func main() { x := 2 y := 4 fmt.Println(x<<1) fmt.Println(y>>1)}output:4 2

进行转化为二进制 然后向左或者向右移动。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对的支持。

声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。

相关文章