原文链接:Golang易错知识点
发布时间:2021-11-17 23:34:25
文章目录
string和’\0’
Golang的string内部就是字节数组,末尾没有’\0’,对于Golang来说,’\0’也是一个普通的字节。其他语言在传输字符串的时候有可能在末尾加’\0’,那么Golang解析的时候会在末尾多了’\0’字符。
就会出现很尴尬的事情。比如C语言传输了’CHINA\0’,Golang解析后,再用’CHINA’比较,就不会相等了,但是打印出来确是一样。用C语言接收处理就不会出现问题。
slice
slice本质是一个结构体,不是指针,尽管是调用make创建。而同样调用make创建的map、channel,却是指针。
参见我另一篇博客《slice在Golang中的实现和应用》 。
WaitGroup使用
1 | // 错误的写法 |
第一种写法是错误的,达不到预期的效果。在当前的循环中,会快速地创建100个协程,无任何阻塞,然后立即执行到wg.Wait(),然而可能 wg.Add(1)一次都没有执行到,所以程序结束了。
切记,wg.Add(1)一定要在协程之外执行。
range产生的临时变量
1 | arr := []int{1, 2, 3, 4, 5} |
1 | [0] 0xc00000a0b8 [1] 0xc00000a0d0 -->0xc00000c330 |
k和v并不是每次分配新的变量,一直是一个变量。使用的时候要小心,要使用值传递。
goroutine泄露
进程内存增加,到最后崩溃,按理说Golang自己管理内存,不存在内存泄露。但是大量使用goroutine,有的地方反复调用开启goroutine,之前的goroutine没有回收,就会造成goroutine泄露。
解决方法,在日志中定期打印goroutine数量,可以调用runtime.NumGoroutine() ,观察是否一直增加。
闭包
1 | n := 0 |
闭包,就是指匿名函数以及匿名函数引用的环境组合的实体。可以看到f函数对n做了修改,对函数来说,n就是本包的全局变量。
闭包与range带来的问题
1 | arr := []int{1, 2, 3, 4, 5} |
1 | arr := []int{1, 2, 3, 4, 5} |
第一个程序可以看到,结果没有达到预期,k和v是引用传递。
第二个程序使用函数参数显示的传入函数中,k和v是值传递。
对象滥用的后果
由于Golang会自己回收内存,因此不担心内存泄漏,可以用大胆地创建对象。但是会带来其他问题,比如网络句柄泄漏、文件句柄泄漏。
Golang会帮你释放对象,但是Golang不会帮你释放对象拥有的资源。