搜索
首页后端开发Golang一文详解Golang中的位操作
一文详解Golang中的位操作Sep 21, 2022 am 11:09 AM
gogolang

本篇文章带大家深入了解下Golang中的位操作,介绍一下详述每个操作符以及它们如何使用的案例,希望对大家有所帮助!

一文详解Golang中的位操作

在计算机内存昂贵,处理能力有限的美好旧时光里,用比较黑客范的位运算方式去处理信息是首选方式(某些情况下只能如此)。时至今日,直接使用位运算仍然是很多计算领域中不可或缺的部分,例如底层系统编程,图形处理,密码学等。【相关推荐:Go视频教程

Go 编程语言支持以下按位运算符:

&   bitwise AND
 |   bitwise OR
 ^   bitwise XOR
&^   AND NOT
>   right shift

本文的余下部分详述了每个操作符以及它们如何使用的案例。

& 运算符

在 Go 中,  & 运算符在两个整型操作数中执行按位 AND 操作。AND 操作具有以下属性:

Given operands a, b
AND(a, b) = 1; only if a = b = 1
               else = 0

AND 运算符具有选择性的把整型数据的位清除为 0 的好的效果。 例如,我们可以使用  & 运算符去清除(设置)最后 4 个最低有效位(LSB)全部为 0 。

func main() {
    var x uint8 = 0xAC    // x = 10101100
    x = x & 0xF0          // x = 10100000
}

所有的位运算都支持简写的赋值形式。 例如,前面的例子可以重写为如下。

func main() {
    var x uint8 = 0xAC    // x = 10101100
    x &= 0xF0             // x = 10100000
}

另外一个巧妙的技巧是:你可以用 & 操作去测试一个数字是奇数还是偶数。原因是当一个数字的二进制的最低位是 1 的时候,那他就是奇数。我们可以用一个数字和 1 进行 & 操作,然后在和 1 做 AND 运算,如果的到的结果是 1 ,那么这个原始的数字就是奇数

import (
    "fmt"
    "math/rand"
)
func main() {
    for x := 0; x <p>在  <a href="https://play.golang.org/p/2mTNOtioNM" target="_blank">Playground</a>  上运行上面的例子</p><h4>
<span class="header-link octicon octicon-link"></span><strong>| 操作符</strong>
</h4><p><code>|</code> 对其整型操作数执行按位<code>或</code>操作。回想一下<code>或</code>操作符具备以下性质:</p><pre class="brush:php;toolbar:false">Given operands a, b
OR(a, b) = 1; when a = 1 or b = 1
              else = 0

我们可以利用按位操作符为给定的整数有选择地设置单个位。例如,在如下示例中我们使用按位将示例数(从低位到高位(MSB))中的第 3 ,第 7 和第 8 位置为 1 。

func main() {
    var a uint8 = 0
    a |= 196
    fmt.Printf("%b", a)
}

// 打印结果  11000100
            ^^   ^

练习场中可运行范例。

在使用位掩码技术为给定的整型数字设置任意位时,运算非常有用。例如,我们可以扩展之前的程序为变量 a 存储的值设置更多的位。

func main() {
    var a uint8 = 0
    a |= 196
    a |= 3
    fmt.Printf("%b", a)
}

// 打印结果 11000111

练习场中可以运行范例。

在前面的程序里,不仅要按位设置十进制的 196,而且要设置低位上的十进制 3。我们还可以继续(上更多的值)设置完所有的位。

位运算的配置用法

现在,回顾一下 AND(a, 1) = a 当且仅当 a = 1。 我们可以利用这个特性去查询其设置位的值。例如,在上述代码中 a & 196 会返回 196 是因为这几位的值在 a 中确实都存在。所以我们可以结合使用 OR 和  AND 运算的方式来分别设置和读取某位的配置值。.

接下来的源码片段演示了这个操作。函数 procstr 会转换字符串的内容。它需要两个参数:第一个, str,是将要被转换的字符串,第二个, conf,是一个使用位掩码的方式指定多重转换配置的整数。

const (
    UPPER  = 1 // 大写字符串
    LOWER  = 2 // 小写字符串
    CAP    = 4 // 字符串单词首字母大写
    REV    = 8 // 反转字符串
)

func main() {
    fmt.Println(procstr("HELLO PEOPLE!", LOWER|REV|CAP))
}

func procstr(str string, conf byte) string {
    // 反转字符串
    rev := func(s string) string {
        runes := []rune(s)
        n := len(runes)
        for i := 0; i <p>在 Playground上面运行代码.</p><p>上面的 <code>procstr("HELLO PEOPLE!", LOWER|REV|CAP)</code> 方法会把字符串变成小写,然后反转字符串,最后把字符串里面的单词首字母变成大写。这个功能是通过设置 <code>conf</code> 里的第二,三,四位的值为 14 来完成的。然后代码使用连续的 if 语句块来获取这些位操作进行对应的字符串转换。</p><h4>
<span class="header-link octicon octicon-link"></span><strong>^ 操作符</strong>
</h4><p>在 Go 中  按位 <code>异或</code> 操作是用 <code>^</code> 来表示的。 <code>异或</code>运算符有如下的特点:</p><pre class="brush:php;toolbar:false">Given operands a, b
XOR(a, b) = 1; only if a != b
     else = 0

异或运算的这个特性可以用来把二进制位的一个值变成另外一个值。举个例子,给到一个 16 进制的值,我们可以使用以下代码切换前8位(从 MSB 开始)的值。

func main() {
    var a uint16 = 0xCEFF
    a ^= 0xFF00 // same a = a ^ 0xFF00
}

// a = 0xCEFF   (11001110 11111111)
// a ^=0xFF00   (00110001 11111111)

在前面的代码片段中,与 1 进行异或的位被翻转(从 0 到 1 或从 1 到  0)。异或 运算的一个实际用途,例如,可以利用 异或运算去比较两个数字的符号是否一样。当 (a ^ b) ≥ 0 (或相反符号的 (a ^ b) )为 <code>true 的时候,两个整数 a,b 具有相同的符号,如下面的程序所示:

func main() {
    a, b := -12, 25
    fmt.Println(&amp;amp;amp;quot;a and b have same sign?&amp;amp;amp;quot;, (a ^ b) &amp;amp;amp;gt;= 0)
}

在 Go 的 Playground运行代码。

当执行上面这个程序的时候,将会打印出:a and b have same sign? false。在 Go Playground 上修改程序里 a ,b 的符号,以便看到不同的结果。

^ 作为取反位运算符 (非)

不像其他语言 (c/c++,Java,Python,Javascript,等), Go 没有专门的一元取反位运算符。取而代之的是,XOR 运算符 ^,也可作为一元取反运算符作用于一个数字。对于给定位 x,在 Go 中 x = 1 ^ x 可以翻转该位。在以下的代码段中我们可以看到使用 ^a 获取变量 a 的取反值的操作。

func main() {
    var a byte = 0x0F
    fmt.Printf(&amp;amp;amp;quot;%08b\n&amp;amp;amp;quot;, a)
    fmt.Printf(&amp;amp;amp;quot;%08b\n&amp;amp;amp;quot;, ^a)
}

// 打印结果
00001111     // var a
11110000     // ^a

练习场中可以运行范例。

&amp;amp;amp;^ 操作符

&amp;amp;amp;^ 操作符意为 与非,是 操作符的简写形式,它们定义如下。

Given operands a, b
AND_NOT(a, b) = AND(a, NOT(b))

如果第二个操作数为 1 那么它则具有清除第一个操作数中的位的趣味特性。

AND_NOT(a, 1) = 0; clears a
AND_NOT(a, 0) = a;

接下来的代码片段使用 AND NOT 操作符,将变量值1010 1011变为 1010 0000,清除了操作数上的低四位。

func main() {
    var a byte = 0xAB
     fmt.Printf(&amp;amp;amp;quot;%08b\n&amp;amp;amp;quot;, a)
     a &amp;amp;amp;amp;^= 0x0F
     fmt.Printf(&amp;amp;amp;quot;%08b\n&amp;amp;amp;quot;, a)
}

// 打印:
10101011
10100000

练习场中运行范例。

> 操作符

与其他 C 的衍生语言类似, Go 使用 和 <code>>> 来表示左移运算符和右移运算符,如下所示:

Given integer operands a and n,
a &amp;amp;amp;gt; n; shifts all bits in a to the right n times

例如,在下面的代码片段中变量 a00000011)的值将会左移位运算符分别移动三次。每次输出结果都是为了说明左移的目的。

func main() {
    var a int8 = 3
    fmt.Printf(&amp;amp;amp;quot;%08b\n&amp;amp;amp;quot;, a)
    fmt.Printf(&amp;amp;amp;quot;%08b\n&amp;amp;amp;quot;, a&amp;amp;amp;lt;p&amp;amp;amp;gt;在 &amp;amp;amp;lt;a href=&amp;amp;amp;quot;https://play.golang.org/p/_lhE8OoZxY&amp;amp;amp;quot; target=&amp;amp;amp;quot;_blank&amp;amp;amp;quot;&amp;amp;amp;gt;Playground&amp;amp;amp;lt;/a&amp;amp;amp;gt; 运行代码&amp;amp;amp;lt;/p&amp;amp;amp;gt;&amp;amp;amp;lt;p&amp;amp;amp;gt;注意每次移动都会将低位右侧补零。相对应,使用右移位操作符进行运算时,每个位均向右方移动,空出的高位补零,如下示例 (有符号数除外,参考下面的算术移位注释)。&amp;amp;amp;lt;/p&amp;amp;amp;gt;&amp;amp;amp;lt;pre class=&amp;amp;amp;quot;brush:php;toolbar:false&amp;amp;amp;quot;&amp;amp;amp;gt;func main() {
 var a uint8 = 120
 fmt.Printf(&amp;amp;amp;quot;%08b\n&amp;amp;amp;quot;, a)
 fmt.Printf(&amp;amp;amp;quot;%08b\n&amp;amp;amp;quot;, a&amp;amp;amp;gt;&amp;amp;amp;gt;1)
 fmt.Printf(&amp;amp;amp;quot;%08b\n&amp;amp;amp;quot;, a&amp;amp;amp;gt;&amp;amp;amp;gt;2)
}

// 打印:
01111000
00111100
00011110

练习场中可以运行范例。

可以利用左移和右移运算中,每次移动都表示一个数的 2 次幂这个特性,来作为某些乘法和除法运算的小技巧。例如,如下代码中,我们可以使用右移运算将 200(存储在变量 a 中)除以 2 。

func main() {
    a := 200
    fmt.Printf(&amp;amp;amp;quot;%d\n&amp;amp;amp;quot;, a&amp;amp;amp;gt;&amp;amp;amp;gt;1)
}

// 打印:
100

练习场 中可以运行范例。

或是通过左移 2 位,将一个数乘以4:

func main() {
    a := 12
    fmt.Printf(&amp;amp;amp;quot;%d\n&amp;amp;amp;quot;, a&amp;amp;amp;lt;p&amp;amp;amp;gt;在 &amp;amp;amp;lt;a href=&amp;amp;amp;quot;https://play.golang.org/p/xuJRcKgMVV&amp;amp;amp;quot; target=&amp;amp;amp;quot;_blank&amp;amp;amp;quot;&amp;amp;amp;gt;练习场&amp;amp;amp;lt;/a&amp;amp;amp;gt; 中可以运行范例。&amp;amp;amp;lt;/p&amp;amp;amp;gt;&amp;amp;amp;lt;p&amp;amp;amp;gt;位移运算符提供了有趣的方式处理二进制值中特定位置的值。例如,下列的代码中,&amp;amp;amp;lt;code&amp;amp;amp;gt;|&amp;amp;amp;lt;/code&amp;amp;amp;gt; 和 &amp;amp;amp;lt;code&amp;amp;amp;gt; 用于设置变量 &amp;amp;amp;lt;code&amp;amp;amp;gt;a&amp;amp;amp;lt;/code&amp;amp;amp;gt; 的第三个 bit 位。&amp;amp;amp;lt;/code&amp;amp;amp;gt;&amp;amp;amp;lt;/p&amp;amp;amp;gt;&amp;amp;amp;lt;pre class=&amp;amp;amp;quot;brush:php;toolbar:false&amp;amp;amp;quot;&amp;amp;amp;gt;func main() {
    var a int8 = 8
    fmt.Printf(&amp;amp;amp;quot;%08b\n&amp;amp;amp;quot;, a)
    a = a | (1&amp;amp;amp;lt;p&amp;amp;amp;gt;可以在 &amp;amp;amp;lt;a href=&amp;amp;amp;quot;https://play.golang.org/p/h7WoP7ieuI&amp;amp;amp;quot; target=&amp;amp;amp;quot;_blank&amp;amp;amp;quot;&amp;amp;amp;gt;练习场&amp;amp;amp;lt;/a&amp;amp;amp;gt; 中运行代码示例。&amp;amp;amp;lt;/p&amp;amp;amp;gt;&amp;amp;amp;lt;p&amp;amp;amp;gt;或者,您可以组合位移运算符和 &amp;amp;amp;lt;code&amp;amp;amp;gt;&amp;amp;amp;amp;&amp;amp;amp;lt;/code&amp;amp;amp;gt; 测试是否设置了第n位,如下面示例所示:&amp;amp;amp;lt;/p&amp;amp;amp;gt;&amp;amp;amp;lt;pre class=&amp;amp;amp;quot;brush:php;toolbar:false&amp;amp;amp;quot;&amp;amp;amp;gt;func main() {
    var a int8 = 12
    if a&amp;amp;amp;amp;(1&amp;amp;amp;lt;p&amp;amp;amp;gt;在 &amp;amp;amp;lt;a href=&amp;amp;amp;quot;https://play.golang.org/p/Ptc7Txk5Jb&amp;amp;amp;quot; target=&amp;amp;amp;quot;_blank&amp;amp;amp;quot;&amp;amp;amp;gt;练习场&amp;amp;amp;lt;/a&amp;amp;amp;gt;中运行代码。&amp;amp;amp;lt;/p&amp;amp;amp;gt;&amp;amp;amp;lt;p&amp;amp;amp;gt;使用  &amp;amp;amp;lt;code&amp;amp;amp;gt;&amp;amp;amp;amp;^&amp;amp;amp;lt;/code&amp;amp;amp;gt; 和位移运算符,我们可以取消设置一个值的某个位。例如,下面的示例将变量 a 的第三位置为 0 :&amp;amp;amp;lt;/p&amp;amp;amp;gt;&amp;amp;amp;lt;pre class=&amp;amp;amp;quot;brush:php;toolbar:false&amp;amp;amp;quot;&amp;amp;amp;gt;func main() {
    var a int8 = 13 
    fmt.Printf(&amp;amp;amp;quot;%04b\n&amp;amp;amp;quot;, a)
    a = a &amp;amp;amp;amp;^ (1 &amp;amp;amp;lt;p&amp;amp;amp;gt;在 &amp;amp;amp;lt;a href=&amp;amp;amp;quot;https://play.golang.org/p/Stjq9oOjKz&amp;amp;amp;quot; target=&amp;amp;amp;quot;_blank&amp;amp;amp;quot;&amp;amp;amp;gt;练习场&amp;amp;amp;lt;/a&amp;amp;amp;gt; 中运行代码。&amp;amp;amp;lt;/p&amp;amp;amp;gt;&amp;amp;amp;lt;h4&amp;amp;amp;gt;
&amp;amp;amp;lt;span class=&amp;amp;amp;quot;header-link octicon octicon-link&amp;amp;amp;quot;&amp;amp;amp;gt;&amp;amp;amp;lt;/span&amp;amp;amp;gt;&amp;amp;amp;lt;strong&amp;amp;amp;gt;关于算术位移运算的笔记&amp;amp;amp;lt;/strong&amp;amp;amp;gt;
&amp;amp;amp;lt;/h4&amp;amp;amp;gt;&amp;amp;amp;lt;p&amp;amp;amp;gt;当要位移的值(左操作数)是有符号值时,Go 自动应用算术位移。在右移操作期间,复制(或扩展)二进制补码符号位以填充位移的空隙。&amp;amp;amp;lt;/p&amp;amp;amp;gt;&amp;amp;amp;lt;h4&amp;amp;amp;gt;
&amp;amp;amp;lt;span class=&amp;amp;amp;quot;header-link octicon octicon-link&amp;amp;amp;quot;&amp;amp;amp;gt;&amp;amp;amp;lt;/span&amp;amp;amp;gt;&amp;amp;amp;lt;strong&amp;amp;amp;gt;总结&amp;amp;amp;lt;/strong&amp;amp;amp;gt;
&amp;amp;amp;lt;/h4&amp;amp;amp;gt;&amp;amp;amp;lt;p&amp;amp;amp;gt;与其它现代运算符一样,Go 支持所有二进制位操作运算符。这篇文章仅仅提供了可以用这些操作符完成的各种黑科技示例。你可以在网络上找到很多文章,特别是 Sean Eron Anderson 写的 &amp;amp;amp;lt;a href=&amp;amp;amp;quot;https://graphics.stanford.edu/~seander/bithacks.html&amp;amp;amp;quot; target=&amp;amp;amp;quot;_blank&amp;amp;amp;quot;&amp;amp;amp;gt;Bit Twiddling Hacks&amp;amp;amp;lt;/a&amp;amp;amp;gt; 。&amp;amp;amp;lt;/p&amp;amp;amp;gt;&amp;amp;amp;lt;p&amp;amp;amp;gt;关注 Vladim &amp;amp;amp;lt;a href=&amp;amp;amp;quot;https://twitter.com/VladimirVivien&amp;amp;amp;quot; target=&amp;amp;amp;quot;_blank&amp;amp;amp;quot;&amp;amp;amp;gt;@vladimirvivien&amp;amp;amp;lt;/a&amp;amp;amp;gt; 的 Twitter。&amp;amp;amp;lt;/p&amp;amp;amp;gt;&amp;amp;amp;lt;p&amp;amp;amp;gt;如果你正在学习 Go,阅读  Vladimir Vivien 关于 Go 的书,名为 &amp;amp;amp;lt;a href=&amp;amp;amp;quot;https://www.packtpub.com/application-development/learning-go-programming&amp;amp;amp;quot; target=&amp;amp;amp;quot;_blank&amp;amp;amp;quot;&amp;amp;amp;gt;Learning Go Programming&amp;amp;amp;lt;/a&amp;amp;amp;gt; 。&amp;amp;amp;lt;/p&amp;amp;amp;gt;&amp;amp;amp;lt;p&amp;amp;amp;gt;这篇文章开始由作者 Vladimir Vivien 发布在 Medium 上,名为 &amp;amp;amp;lt;a href=&amp;amp;amp;quot;https://medium.com/learning-the-go-programming-language/bit-hacking-with-go-e0acee258827#.2hof13ia5&amp;amp;amp;quot; target=&amp;amp;amp;quot;_blank&amp;amp;amp;quot;&amp;amp;amp;gt;Bit Hacking with Go&amp;amp;amp;lt;/a&amp;amp;amp;gt;。&amp;amp;amp;lt;/p&amp;amp;amp;gt;&amp;amp;amp;lt;blockquote&amp;amp;amp;gt;&amp;amp;amp;lt;p&amp;amp;amp;gt;英文原文地址:https://dev.to/vladimirvivien/bit-hacking-with-go&amp;amp;amp;lt;/p&amp;amp;amp;gt;&amp;amp;amp;lt;/blockquote&amp;amp;amp;gt;&amp;amp;amp;lt;p&amp;amp;amp;gt;更多编程相关知识,请访问:&amp;amp;amp;lt;a href=&amp;amp;amp;quot;https://www.php.cn/course.html&amp;amp;amp;quot; target=&amp;amp;amp;quot;_blank&amp;amp;amp;quot; textvalue=&amp;amp;amp;quot;编程视频&amp;amp;amp;quot;&amp;amp;amp;gt;编程视频&amp;amp;amp;lt;/a&amp;amp;amp;gt;!!&amp;amp;amp;lt;/p&amp;amp;amp;gt;

以上是一文详解Golang中的位操作的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文转载于:learnku。如有侵权,请联系admin@php.cn删除
go语言有没有缩进go语言有没有缩进Dec 01, 2022 pm 06:54 PM

go语言有缩进。在go语言中,缩进直接使用gofmt工具格式化即可(gofmt使用tab进行缩进);gofmt工具会以标准样式的缩进和垂直对齐方式对源代码进行格式化,甚至必要情况下注释也会重新格式化。

一文浅析Golang中的闭包一文浅析Golang中的闭包Nov 21, 2022 pm 08:36 PM

闭包(closure)是一个函数以及其捆绑的周边环境状态(lexical environment,词法环境)的引用的组合。 换而言之,闭包让开发者可以从内部函数访问外部函数的作用域。 闭包会随着函数的创建而被同时创建。

聊聊Golang中的几种常用基本数据类型聊聊Golang中的几种常用基本数据类型Jun 30, 2022 am 11:34 AM

本篇文章带大家了解一下golang 的几种常用的基本数据类型,如整型,浮点型,字符,字符串,布尔型等,并介绍了一些常用的类型转换操作。

go语言为什么叫gogo语言为什么叫goNov 28, 2022 pm 06:19 PM

go语言叫go的原因:想表达这门语言的运行速度、开发速度、学习速度(develop)都像gopher一样快。gopher是一种生活在加拿大的小动物,go的吉祥物就是这个小动物,它的中文名叫做囊地鼠,它们最大的特点就是挖洞速度特别快,当然可能不止是挖洞啦。

一文详解Go中的并发【20 张动图演示】一文详解Go中的并发【20 张动图演示】Sep 08, 2022 am 10:48 AM

Go语言中各种并发模式看起来是怎样的?下面本篇文章就通过20 张动图为你演示 Go 并发,希望对大家有所帮助!

【整理分享】一些GO面试题(附答案解析)【整理分享】一些GO面试题(附答案解析)Oct 25, 2022 am 10:45 AM

本篇文章给大家整理分享一些GO面试题集锦快答,希望对大家有所帮助!

tidb是go语言么tidb是go语言么Dec 02, 2022 pm 06:24 PM

是,TiDB采用go语言编写。TiDB是一个分布式NewSQL数据库;它支持水平弹性扩展、ACID事务、标准SQL、MySQL语法和MySQL协议,具有数据强一致的高可用特性。TiDB架构中的PD储存了集群的元信息,如key在哪个TiKV节点;PD还负责集群的负载均衡以及数据分片等。PD通过内嵌etcd来支持数据分布和容错;PD采用go语言编写。

聊聊Golang自带的HttpClient超时机制聊聊Golang自带的HttpClient超时机制Nov 18, 2022 pm 08:25 PM

​在写 Go 的过程中经常对比这两种语言的特性,踩了不少坑,也发现了不少有意思的地方,下面本篇就来聊聊 Go 自带的 HttpClient 的超时机制,希望对大家有所帮助。

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

仓库:如何复兴队友
1 个月前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前By尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
1 个月前By尊渡假赌尊渡假赌尊渡假赌

热工具

EditPlus 中文破解版

EditPlus 中文破解版

体积小,语法高亮,不支持代码提示功能

螳螂BT

螳螂BT

Mantis是一个易于部署的基于Web的缺陷跟踪工具,用于帮助产品缺陷跟踪。它需要PHP、MySQL和一个Web服务器。请查看我们的演示和托管服务。

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

PhpStorm Mac 版本

PhpStorm Mac 版本

最新(2018.2.1 )专业的PHP集成开发工具