Go语言的100个错误使用场景(30.docx
第
Go语言的100个错误使用场景(30
前言
4.控制结构
4.1忽视元素在range循环中是拷贝(#30)
4.2忽略在range循环中如何评估表达式(#31)
4.3忽略在range中使用指针元素的影响(#32)
4.4对map遍历的错误假设(#33)
4.5忽略break的作用(#34)
4.6在循环中使用defer(#35)
5.字符串
5.1不理解rune的概念(#36)
5.2不准确的字符串迭代(#37)
5.3误用裁剪函数(#38)
5.4优化不足的字符串拼接(#39)
小结
大家好,这里是白泽。《Go语言的100个错误以及如何避免》是最近朋友推荐我阅读的书籍,我初步浏览之后,大为惊喜。就像这书中第一章的标题说到的:Go:Simpletolearnbuthardtomaster,整本书通过分析100个错误使用Go语言的场景,带你深入理解Go语言。
我的愿景是以这套文章,在保持权威性的基础上,脱离对原文的依赖,对这100个场景进行篇幅合适的中文讲解。所涉内容较多,总计约8w字,这是该系列的第四篇文章,对应书中第30-39个错误场景。
当然,如果您是一位Go学习的新手,您可以在我开源的学习仓库中,找到针对《Go程序设计语言》英文书籍的配套笔记,其他所有文章也会整理收集在其中。
B站:白泽talk,公众号【白泽talk】,聊天交流群:622383022,原书电子版可以加群获取。
前文链接:
《Go语言的100个错误使用场景(1-10)|代码和项目组织》
《Go语言的100个错误使用场景(11-20)|项目组织和数据类型》
《Go语言的100个错误使用场景(21-29)|数据类型》
4.控制结构
章节概述:
range循环如何赋值
处理range循环和引用
避免遍历map导致问题
在循环内使用defer
4.1忽视元素在range循环中是拷贝(#30)
range循环允许遍历的数据类型:
String
数组的指针
channel中取值
s:=[]string{a,b,c}
//保留值
for_,vranges{
fmt.Println(value=%s\n,v)
//保留索引
fori:=ranges{
fmt.Println(index=%d\n,i)
值拷贝:
typeaccountstruct{
balancefloat32
accounts:=[]account{
{balance:100.},
{balance:200.},
{balance:300.},
for_,a:=rangeaccounts{
a.balance+=1000
//打印accounts切片,得到的结果为[{100},{200},{300}],赋值没有影响到切片
[{100},{200},{300}]
Go语言当中,所有的赋值都是拷贝:
如果函数返回一个结构体,表示这个结构体的拷贝。
如果函数返回一个结构体的指针,表示一个内存地址的拷贝。
因此上述range循环赋值的过程,只是将1000添加到了a这个拷贝的变量上。
修正方案:
fori:=rangeaccounts{
accounts[i].balance==1000
fori:=0;ilen(accounts);i++{
accounts[i].balance==1000
如果业务逻辑简单,则推荐第一种,因为编码更少,如果逻辑复杂则推荐第二种,因为可能需要对i的大小进行逻辑判断。
特殊情况:
accounts:=[]*account{
{balance:100.},
{balance:200.},
{balance:300.},
for_,a:=rangeaccounts{
a.balance+=1000
//打印accounts切片
[{1100},{1200},{1300}]
遍历指针类型的accounts可以将修改在切片上生效,因为指向的内存是同一份。但是性能会比直接修改struct更低,这一点将在(#91)讲CPU