Open shownb opened 6 years ago
多个协程同时写也会出现fatal error: concurrent map writes的错误 如下代码是问题代码
for _,v :=range accounts {
wg.Add(1)
go func (w *sync.WaitGroup,v string) {
tmp[v],_ = conn.EthGetBalance(v,"latest")
w.Done()
}(wg,v)
}
解决方法是加锁
go func (w *sync.WaitGroup,v string,lock *sync.Mutex) {
ret,_ := conn.EthGetBalance(v,"latest")
lock.Lock()
tmp[v]=ret
lock.Unlock()
w.Done()
}(wg,v,lock)
}
go不会对 类型是interface{} 的 slice 进行转换 。
既然空的 interface 可以接受任何类型的参数,那么一个 interface{}类型的 slice 是不是就可以接受任何类型的 slice ?
上面的代码是按照我们的假设修改的,执行之后竟然会报
错误,why? 这个错误说明 go 没有帮助我们自动把 slice 转换成 interface{} 类型的 slice,所以出错了。go 不会对 类型是interface{} 的 slice 进行转换 。为什么 go 不帮我们自动转换,一开始我也很好奇,最后终于在 go 的 wiki 中找到了答案 https://github.com/golang/go/wiki/InterfaceSlice 大意是 interface{} 会占用两个字长的存储空间,一个是自身的 methods 数据,一个是指向其存储值的指针,也就是 interface 变量存储的值,因而 slice []interface{} 其长度是固定的N2,但是 []T 的长度是Nsizeof(T),两种 slice 实际存储值的大小是有区别的(文中只介绍两种 slice 的不同,至于为什么不能转换猜测可能是 runtime 转换代价比较大)。
不用make来初始化map,会生成一个nil的map
会产生 panic: assignment to entry in nil map 因为他开始是个nil指针,自然找不到指向哪里,自然赋值失败。
golang的每个变量都有一个内存地址。 var nilpointer map[int]string //定义了是一个map变量,他有内存地址存储这个变量。nilpointer实际是一个指针,但现在他默认是nil,空指针。
make函数创建map返回的是一个指针类型。
https://play.golang.org/p/kYtUd7XAqXs
切片作为参数时候,在函数内append会有坑
如果切片作为参数传入的时候,在函数内不用append来扩容的话,是可以作为引用来用的。 但如果用了append,就改变了切片里面的指针地址,达不到作为引用效果了。 当slice_c=append(slice_a,slice_b)中len(slice_a)+len(slice_b)<=cap(slice_a)时不会扩容,否则会被扩为cap(slice_a)的两倍,如果slice len大于1024了,会扩容四分之一cap。具体实现源码如下:
从例2可以看见,append返回的slice指向了个新的地址。但是即使没扩容,slice指向同一个地址的情况下,为何slice_c还是不等于slice_a呢?其实slice不是单纯一个指针,而是个C的struct实现的 详见 https://segmentfault.com/a/1190000012008869