利用位运算符实现一个字段表示多个bool类型属性

来源:互联网 发布:免费下载音乐软件 编辑:程序博客网 时间:2024/05/29 09:00

上周看到的,记录一下

假设一个类中有多个字段是bool类型,例如微博用户User的特权:
1.微博红名
2.微博达人
3.Vip会员
4.超级Vip会员
5.金V
6.蓝V

User的定义方式1:

type User struct {    name string    isHongMing bool    isDaRen bool    isVip bool    isSuperVip bool    ...}

对每个属性设置相应的get和set方法。
这种方式在数据库存储时需要的字段会比较多,且随着业务的变化需要修改数据库表。

若使用位运算符,可实现一个字段表示多个bool类型的属性,数据库表中只需要存储一个字段,且不需要根据业务的变化而修改表的列,int64可表示64种属性,满足大多数需求。
方式2:

type User struct {    name string    pre uint8}

上面定义了一个uint8类型的pre,默认值为0,二进制为0000 0000,八位可以表示八种bool类型的属性,我们用1来表示true,0表示false,事先规定好每一位所表示的属性,例如

    /*    0000 0000    0000 0001 IsHongMing 表示具有红名特权,十进制为1    0000 0010 IsDaRen    表示具有达人特权,十进制为2    0000 0100 IsVip      表示具有Vip特权,十进制为4    0000 1000 IsSuperVip 表示具有SVip特权    ...     */

初始化一个用户:

    var user User    user.name = "Sheldon"    user.pre = 0

位预算表:

这里写图片描述

初始化后Sheldon的特权为0000 0000
我们想给Sheldon一个红名的特权,需要将Sheldon的pre的第一位赋为1,这里我们使用按位或运算,让0与1做按位或,结果为 0000 0001

此时Sheldon的pre为1

我们又想给Sheldon达人的权限,让他的权限由0000 0001变成0000 0011,若保持第一位不变,第二位变为1,需要将1左移1位 1<<1,让0000 0001与 0000 0010做或运算
这里写图片描述
此时Sheldon的pre为3
以此类推,若想将pre的第n位设置为1,则需要让pre和1<<(n-1)做或运算 pre | 1 << (n-1)

当我们想取消用户的某一项特权将其置为false时,使用按位异或运算,将对应的位设置为0

例如取消Sheldon的达人权限,只需要让3与1<<1做按位异或
这里写图片描述

PS:若当前某一位为0时再将其设置为0,结果将变成1,所以在将某一属性设置为false前需要先判断其当前值是0还是1,是1的话再做异或运算

下面说说怎么对某一属性做判断。

当Sheldon的pre为3,我们想判断他是否具有达人的特权,这时将3和1<<1作按位与运算,并与其位置作==判断

这里写图片描述
代码为:

    result := user.pre & posi    return result == posi

结果返回true

代码如下:

WeiboUser.go

package maintype User struct {    name string    pre uint8}func SetPre(user User, isSet bool, posi uint8) User{    /*    parameters:        user : user        isSet : set the prerogative to true or false        posi : the position of prerogative    return:        user     */    if isSet == true{        user.pre = user.pre | posi    }else {        user.pre = user.pre ^ posi    }    return user}func GetPre(user User, posi uint8) bool{    /*    parameters:        user : user        posi : the position of prerogative    return:        true or false     */    result := user.pre & posi    return result == posi}

main.go

package mainimport "fmt"func main() {    var user User    user.name = "Sheldon"    user.pre = 0    fmt.Printf("user is DaRen:%v\n", GetPre(user,1<<1))    user = SetPre(user, true, 1<<1)    user = SetPre(user, true, 1<<0)    fmt.Println(user.pre)    fmt.Printf("user is DaRen:%v\n", GetPre(user,1<<1))}

执行结果:

$ ./data_type.exeuser is DaRen:false3user is DaRen:true
阅读全文
0 0
原创粉丝点击