go常见的坑
1、 for循环中使用短变量声明初始值
案例1:
type Data struct {
d *int
}
func main() {
list := make([]Data, 0)
for i := 0; i < 10; i++ {
list = append(list, Data{ d: &i})
}
for _, item := range list {
fmt.Printf("%d ",*item.d)
}
fmt.Println()
}
预期输出:
0 1 2 3 4 5 6 7 8 9
实际输出:
10 10 10 10 10 10 10 10 10 10
原因是在Go中,变量声明之后,在同一作用域中,对于同一变量名,后续的声明是不会分配新的变量(即没有新的地址空间),所以这里的 i 的内存地址始终不变。因此每次变量 i 指向的地址值 最终为10。对于该问题,使用一个新的变量存储,然后再想slice中append临时变量的地址地址即可,如下:
for i := 0; i < 10; i++ {
temp := i
list = append(list, Data{ d: &temp})
}
案例2:
for-range中初始化使用短变量
func main() {
sl := []int{1,2,3,4,5,6,7,8,9}
list := make([]*int, len(sl))
for i, v := range sl{
list[i] = &v
}
fmt.Println(list)
}
此处list中元素的地址都是指向0xc00012a000,其原因与上述一致。解决方法也是使用一个临时变量存储即可
2、go并发的坑 -闭包陷阱
案例1:
package main import (
"fmt"
"sync"
"time"
) func main() {
wg := sync.WaitGroup{}
wg.Add(2)
for i := 0; i < 2; i++ {
go func() {
prefix := fmt.Sprintf("%d", i+1)
for c := 'A'; c <= 'A'; c++ {
fmt.Printf("%s:%c\n", prefix, c)
time.Sleep(time.Millisecond)
}
wg.Done()
}()
}
fmt.Println("Card")
wg.Wait() }
输出如下:

案例2:
package main import (
"fmt"
"runtime"
"time"
) func main() {
var a [10]int
for i := 0; i < 10; i++ {
go func() {
for {
a[i]++
runtime.Gosched()
}
}()
}
time.Sleep(time.Millisecond)
fmt.Println("a", a)
}

案例3:
func main() {
var wg sync.WaitGroup
sl := []int{1,2,3,4,5,6,7,8,9}
for i, v := range sl{
go func() {
defer wg.Done()
fmt.Println(i, v)
}()
wg.Add(1)
}
wg.Wait()
}
实际输出如下:
8 9
8 9
8 9
8 9
8 9
8 9
8 9
8 9
8 9
这里输出的结果,i, v都是一样的,其原理和上面一样,也是由于变量只会在第一次声明时初始化。这里解决办法是直接使用闭包函数传参,将i,v作为参数传递进去(会进行拷贝),从而达到预期效果,改进代码如下:
go func(i, v int) { // 注意这里的参数变化
defer wg.Done()
fmt.Println(i, v)
}(i, v)
3、defer的坑 -闭包陷阱
案例1、
package main
import "fmt"
func main() {
for i := 3; i > 0; i-- {
defer func() {
fmt.Print(i, " ")
}()
}
}
问题解析:这里是极度容易踩坑的地方,由于defer这里调用的func没有参数,等执行的时候,i已经为0(按3 2 1逆序,最后一个i=1时,i--的结果最后是0),所以这里输出3个0 。
如果还不理解:
package main
import "fmt"
func main() {
for i := 3; i > 1; i-- { // 循环满足条件的是 3 2,
defer func() { // 因为func 没有参数,defer运行最后i--即 2-- 结果为 1
fmt.Print(i, " ") // 循环2次 结果均为 1
}()
}
}//输出 1 1
go常见的坑的更多相关文章
- Golang开发者常见的坑
Golang开发者常见的坑 目录 [−] 初级 开大括号不能放在单独的一行 未使用的变量 未使用的Imports 简式的变量声明仅可以在函数内部使用 使用简式声明重复声明变量 偶然的变量隐藏Accid ...
- 纯Socket(BIO)长链接编程的常见的坑和填坑套路
本文章纯属个人经验总结,伪代码也是写文章的时候顺便白板编码的,可能有逻辑问题,请帮忙指正,谢谢. Internet(全球互联网)是无数台机器基于TCP/IP协议族相互通信产生的.TCP/IP协议族分了 ...
- 学习笔记之C/C++指针使用常见的坑
https://mp.weixin.qq.com/s/kEHQjmhNtSmV3MgHzw6YeQ 避免内存泄露 不再用到的内存没有释放,就叫做内存泄露 在C/C++中,通过动态内存分配函数(如mal ...
- 详讲H5、WebApp项目中常见的坑以及注意事项
首先我们中会有一些常用的meta标签,如下: <!--防止手机中网页放大和缩小--> <meta name="viewport" content="wi ...
- Android中常见的坑有哪些?
对于安卓开发入门级程序猿而言,由于不熟悉代码.工具等等,掉进一些坑中是难免的,今天小编在网上看到一位大神总结的Android开发中比较常见的坑及其原因和解决办法,赶脚还不错,分享出来,给大家提个醒. ...
- Android使用WebView开发常见的坑
原文链接:http://mp.weixin.qq.com/s?__biz=MzAwODE1NTI2MQ==&tempkey=uP3a%2BOgIN7vPbLfJp3BTCl2KabYi1%2F ...
- Go语言常见的坑
目录 1. 可变参数是空接口类型 2. 数组是值传递 3.map遍历是顺序不固定 4. 返回值被屏蔽 5.recover必须在defer函数中运行 6. main函数提前退出 7.通过Sleep来回避 ...
- 【常见踩坑】USB调试安装失败(Installation failed with message INSTALL_CANCELED_BY_USER)
一.写在前面 最近一直在忙活着项目重构,忙活了一个多月(那是天天加班,不分昼夜呀,ps:这不是我司要求的哈),终于把沉积了三四年的老项目给重构了,目前在测试阶段,也总算有了点闲时来跟大家分享分享一些问 ...
- Mybatis通过注解方式实现批量插入数据库 及 常见的坑
原文地址:http://f0rb.iteye.com/blog/1207384 MyBatis中通过xml文件配置数据库批量操作的文章很多,比如这篇http://www.cnblogs.com/xcc ...
- Spring,SpringMvc配置常见的坑,注解的使用注意事项,applicationContext.xml和spring.mvc.xml配置注意事项,spring中的事务失效,事务不回滚原因
1.Spring中的applicationContext.xml配置错误导致的异常 异常信息: org.apache.ibatis.binding.BindingException: Invalid ...
随机推荐
- [编程基础] C++多线程入门4-数据共享和资源竞争
原始C++标准仅支持单线程编程.新的C++标准(称为C++11或C++0x)于2011年发布.在C++11中,引入了新的线程库.因此运行本文程序需要C++至少符合C++ 11标准. 4 数据共享和资源 ...
- [python]《Python编程快速上手:让繁琐工作自动化》学习笔记4
1. 处理Excel 电子表格笔记(第12章)(代码下载) 本文主要介绍openpyxl 的2.5.12版处理excel电子表格,原书是2.1.4 版,OpenPyXL 团队会经常发布新版本.不过不用 ...
- HBase详解(05) - HBase优化 整合Phoenix 集成Hive
HBase详解(05) - HBase优化 整合Phoenix 集成Hive HBase优化 预分区 每一个region维护着startRow与endRowKey,如果加入的数据符合某个region维 ...
- ArcGIS工具 - 统计工具数量
ESRI作为GIS行业中的龙头,代表产品ArcGIS也在不断地优化和升级,从10.0开始已发布了8个版本,其工具箱(ToolBox)是它一个特色,每个版本的工具箱数量是不相同的,为源地理来教您如何统计 ...
- maven依赖管理,生命周期,插件
依赖配置 依赖指当前项目运行所需的jar,一个项目可以设置多个依赖,在pom.xml中格式如下 <!--设置当前项目所依赖的所有jar--> <dependencies> &l ...
- 除了Navicat和DBeaver,还有没有免费又好用的数据库管理/SQL工具推荐
很多国内SQL学习者和开发者对Navicat.DBeaver等国外数据库管理工具已经很熟悉了.但是,有没有比他们更适合SQL开发者的数据库管理/SQL工具呢?这里,笔者结合自己的调研来聊一下. 笔者做 ...
- Consumer接口-Consumer接口的默认方法andThen
Consumer接口 java.util.function.Consumer<T〉接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据,其数据类型由泛型决定. 抽象方法:a ...
- 模拟BS服务器分析-模拟BS服务器代码实现
模拟BS服务器分析 模拟网站服务器,使用浏览器访问自己编写的服务端程序,查看网页效果. 服务器要给客户端回写一个信息,回写一个html页面(文件)我们需要读取index.html文件,就必须的知道这个 ...
- 洛谷 P3916 图的遍历
题目链接 最容易想的思路:对于每一个点都进行dfs/bfs,时间复杂度为O(n*(n+m)),显然超时 可以使用类似记忆化的操作,一个点能到达的最大值是自己所有能达到的边的最大值,则可以递归来做 但有 ...
- 登山(等级考试4级 测试卷 T1)
这道题目与 重启系统(等级考试4级 2021-03 T4)重启系统(等级考试4级 2021-03 T4) - 王浩泽 - 博客园 (cnblogs.com) 非常相似,于是乎呢就在这个程序上面改一改就 ...