本篇文章带大家深入了解下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;quot;a and b have same sign?&amp;amp;quot;, (a ^ b) &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;quot;%08b\n&amp;amp;quot;, a) fmt.Printf(&amp;amp;quot;%08b\n&amp;amp;quot;, ^a) } // 打印结果 00001111 // var a 11110000 // ^a
在练习场中可以运行范例。
&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;quot;%08b\n&amp;amp;quot;, a) a &amp;amp;amp;^= 0x0F fmt.Printf(&amp;amp;quot;%08b\n&amp;amp;quot;, a) } // 打印: 10101011 10100000
在练习场中运行范例。
> 操作符
与其他 C 的衍生语言类似, Go 使用 和 <code>>>
来表示左移运算符和右移运算符,如下所示:
Given integer operands a and n, a &amp;amp;gt; n; shifts all bits in a to the right n times
例如,在下面的代码片段中变量 a
(00000011
)的值将会左移位运算符分别移动三次。每次输出结果都是为了说明左移的目的。
func main() { var a int8 = 3 fmt.Printf(&amp;amp;quot;%08b\n&amp;amp;quot;, a) fmt.Printf(&amp;amp;quot;%08b\n&amp;amp;quot;, a&amp;amp;lt;p&amp;amp;gt;在 &amp;amp;lt;a href=&amp;amp;quot;https://play.golang.org/p/_lhE8OoZxY&amp;amp;quot; target=&amp;amp;quot;_blank&amp;amp;quot;&amp;amp;gt;Playground&amp;amp;lt;/a&amp;amp;gt; 运行代码&amp;amp;lt;/p&amp;amp;gt;&amp;amp;lt;p&amp;amp;gt;注意每次移动都会将低位右侧补零。相对应,使用右移位操作符进行运算时,每个位均向右方移动,空出的高位补零,如下示例 (有符号数除外,参考下面的算术移位注释)。&amp;amp;lt;/p&amp;amp;gt;&amp;amp;lt;pre class=&amp;amp;quot;brush:php;toolbar:false&amp;amp;quot;&amp;amp;gt;func main() { var a uint8 = 120 fmt.Printf(&amp;amp;quot;%08b\n&amp;amp;quot;, a) fmt.Printf(&amp;amp;quot;%08b\n&amp;amp;quot;, a&amp;amp;gt;&amp;amp;gt;1) fmt.Printf(&amp;amp;quot;%08b\n&amp;amp;quot;, a&amp;amp;gt;&amp;amp;gt;2) } // 打印: 01111000 00111100 00011110
在 练习场中可以运行范例。
可以利用左移和右移运算中,每次移动都表示一个数的 2 次幂这个特性,来作为某些乘法和除法运算的小技巧。例如,如下代码中,我们可以使用右移运算将 200
(存储在变量 a 中)除以 2 。
func main() { a := 200 fmt.Printf(&amp;amp;quot;%d\n&amp;amp;quot;, a&amp;amp;gt;&amp;amp;gt;1) } // 打印: 100
在 练习场 中可以运行范例。
或是通过左移 2 位,将一个数乘以4:
func main() { a := 12 fmt.Printf(&amp;amp;quot;%d\n&amp;amp;quot;, a&amp;amp;lt;p&amp;amp;gt;在 &amp;amp;lt;a href=&amp;amp;quot;https://play.golang.org/p/xuJRcKgMVV&amp;amp;quot; target=&amp;amp;quot;_blank&amp;amp;quot;&amp;amp;gt;练习场&amp;amp;lt;/a&amp;amp;gt; 中可以运行范例。&amp;amp;lt;/p&amp;amp;gt;&amp;amp;lt;p&amp;amp;gt;位移运算符提供了有趣的方式处理二进制值中特定位置的值。例如,下列的代码中,&amp;amp;lt;code&amp;amp;gt;|&amp;amp;lt;/code&amp;amp;gt; 和 &amp;amp;lt;code&amp;amp;gt; 用于设置变量 &amp;amp;lt;code&amp;amp;gt;a&amp;amp;lt;/code&amp;amp;gt; 的第三个 bit 位。&amp;amp;lt;/code&amp;amp;gt;&amp;amp;lt;/p&amp;amp;gt;&amp;amp;lt;pre class=&amp;amp;quot;brush:php;toolbar:false&amp;amp;quot;&amp;amp;gt;func main() { var a int8 = 8 fmt.Printf(&amp;amp;quot;%08b\n&amp;amp;quot;, a) a = a | (1&amp;amp;lt;p&amp;amp;gt;可以在 &amp;amp;lt;a href=&amp;amp;quot;https://play.golang.org/p/h7WoP7ieuI&amp;amp;quot; target=&amp;amp;quot;_blank&amp;amp;quot;&amp;amp;gt;练习场&amp;amp;lt;/a&amp;amp;gt; 中运行代码示例。&amp;amp;lt;/p&amp;amp;gt;&amp;amp;lt;p&amp;amp;gt;或者,您可以组合位移运算符和 &amp;amp;lt;code&amp;amp;gt;&amp;amp;amp;&amp;amp;lt;/code&amp;amp;gt; 测试是否设置了第n位,如下面示例所示:&amp;amp;lt;/p&amp;amp;gt;&amp;amp;lt;pre class=&amp;amp;quot;brush:php;toolbar:false&amp;amp;quot;&amp;amp;gt;func main() { var a int8 = 12 if a&amp;amp;amp;(1&amp;amp;lt;p&amp;amp;gt;在 &amp;amp;lt;a href=&amp;amp;quot;https://play.golang.org/p/Ptc7Txk5Jb&amp;amp;quot; target=&amp;amp;quot;_blank&amp;amp;quot;&amp;amp;gt;练习场&amp;amp;lt;/a&amp;amp;gt;中运行代码。&amp;amp;lt;/p&amp;amp;gt;&amp;amp;lt;p&amp;amp;gt;使用 &amp;amp;lt;code&amp;amp;gt;&amp;amp;amp;^&amp;amp;lt;/code&amp;amp;gt; 和位移运算符,我们可以取消设置一个值的某个位。例如,下面的示例将变量 a 的第三位置为 0 :&amp;amp;lt;/p&amp;amp;gt;&amp;amp;lt;pre class=&amp;amp;quot;brush:php;toolbar:false&amp;amp;quot;&amp;amp;gt;func main() { var a int8 = 13 fmt.Printf(&amp;amp;quot;%04b\n&amp;amp;quot;, a) a = a &amp;amp;amp;^ (1 &amp;amp;lt;p&amp;amp;gt;在 &amp;amp;lt;a href=&amp;amp;quot;https://play.golang.org/p/Stjq9oOjKz&amp;amp;quot; target=&amp;amp;quot;_blank&amp;amp;quot;&amp;amp;gt;练习场&amp;amp;lt;/a&amp;amp;gt; 中运行代码。&amp;amp;lt;/p&amp;amp;gt;&amp;amp;lt;h4&amp;amp;gt; &amp;amp;lt;span class=&amp;amp;quot;header-link octicon octicon-link&amp;amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;&amp;amp;lt;strong&amp;amp;gt;关于算术位移运算的笔记&amp;amp;lt;/strong&amp;amp;gt; &amp;amp;lt;/h4&amp;amp;gt;&amp;amp;lt;p&amp;amp;gt;当要位移的值(左操作数)是有符号值时,Go 自动应用算术位移。在右移操作期间,复制(或扩展)二进制补码符号位以填充位移的空隙。&amp;amp;lt;/p&amp;amp;gt;&amp;amp;lt;h4&amp;amp;gt; &amp;amp;lt;span class=&amp;amp;quot;header-link octicon octicon-link&amp;amp;quot;&amp;amp;gt;&amp;amp;lt;/span&amp;amp;gt;&amp;amp;lt;strong&amp;amp;gt;总结&amp;amp;lt;/strong&amp;amp;gt; &amp;amp;lt;/h4&amp;amp;gt;&amp;amp;lt;p&amp;amp;gt;与其它现代运算符一样,Go 支持所有二进制位操作运算符。这篇文章仅仅提供了可以用这些操作符完成的各种黑科技示例。你可以在网络上找到很多文章,特别是 Sean Eron Anderson 写的 &amp;amp;lt;a href=&amp;amp;quot;https://graphics.stanford.edu/~seander/bithacks.html&amp;amp;quot; target=&amp;amp;quot;_blank&amp;amp;quot;&amp;amp;gt;Bit Twiddling Hacks&amp;amp;lt;/a&amp;amp;gt; 。&amp;amp;lt;/p&amp;amp;gt;&amp;amp;lt;p&amp;amp;gt;关注 Vladim &amp;amp;lt;a href=&amp;amp;quot;https://twitter.com/VladimirVivien&amp;amp;quot; target=&amp;amp;quot;_blank&amp;amp;quot;&amp;amp;gt;@vladimirvivien&amp;amp;lt;/a&amp;amp;gt; 的 Twitter。&amp;amp;lt;/p&amp;amp;gt;&amp;amp;lt;p&amp;amp;gt;如果你正在学习 Go,阅读 Vladimir Vivien 关于 Go 的书,名为 &amp;amp;lt;a href=&amp;amp;quot;https://www.packtpub.com/application-development/learning-go-programming&amp;amp;quot; target=&amp;amp;quot;_blank&amp;amp;quot;&amp;amp;gt;Learning Go Programming&amp;amp;lt;/a&amp;amp;gt; 。&amp;amp;lt;/p&amp;amp;gt;&amp;amp;lt;p&amp;amp;gt;这篇文章开始由作者 Vladimir Vivien 发布在 Medium 上,名为 &amp;amp;lt;a href=&amp;amp;quot;https://medium.com/learning-the-go-programming-language/bit-hacking-with-go-e0acee258827#.2hof13ia5&amp;amp;quot; target=&amp;amp;quot;_blank&amp;amp;quot;&amp;amp;gt;Bit Hacking with Go&amp;amp;lt;/a&amp;amp;gt;。&amp;amp;lt;/p&amp;amp;gt;&amp;amp;lt;blockquote&amp;amp;gt;&amp;amp;lt;p&amp;amp;gt;英文原文地址:https://dev.to/vladimirvivien/bit-hacking-with-go&amp;amp;lt;/p&amp;amp;gt;&amp;amp;lt;/blockquote&amp;amp;gt;&amp;amp;lt;p&amp;amp;gt;更多编程相关知识,请访问:&amp;amp;lt;a href=&amp;amp;quot;https://www.php.cn/course.html&amp;amp;quot; target=&amp;amp;quot;_blank&amp;amp;quot; textvalue=&amp;amp;quot;编程视频&amp;amp;quot;&amp;amp;gt;编程视频&amp;amp;lt;/a&amp;amp;gt;!!&amp;amp;lt;/p&amp;amp;gt;
以上是一文详解Golang中的位操作的详细内容。更多信息请关注PHP中文网其他相关文章!

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

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

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

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

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

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


热AI工具

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

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

Undress AI Tool
免费脱衣服图片

Clothoff.io
AI脱衣机

AI Hentai Generator
免费生成ai无尽的。

热门文章

热工具

EditPlus 中文破解版
体积小,语法高亮,不支持代码提示功能

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

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

Dreamweaver CS6
视觉化网页开发工具

PhpStorm Mac 版本
最新(2018.2.1 )专业的PHP集成开发工具