Golang易错知识点

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使用

// 错误的写法
func main() {
    wg := sync.WaitGroup{}
    for i := 0; i < 100; i++ {
        go func(i int) {
             wg.Add(1)
            fmt.Println(i)
            wg.Done()
        }(i)
    }
    wg.Wait()
}


// 正确的写法
func main() {
    wg := sync.WaitGroup{}
    for i := 0; i < 100; i++ {
        wg.Add(1)
        go func(i int) {
            fmt.Println(i)
            wg.Done()
        }(i)
    }
    wg.Wait()
}

第一种写法是错误的,达不到预期的效果。在当前的循环中,会快速地创建100个协程,无任何阻塞,然后立即执行到wg.Wait(),然而可能 wg.Add(1)一次都没有执行到,所以程序结束了。

切记,wg.Add(1)一定要在协程之外执行。

range产生的临时变量

	arr := []int{1, 2, 3, 4, 5}
	for k,v := range arr {
		fmt.Printf("[%d] %p [%d] %p -->%p\n", k, &k, v, &v, &(arr[k]))
	}

[0] 0xc00000a0b8 [1] 0xc00000a0d0 -->0xc00000c330
[1] 0xc00000a0b8 [2] 0xc00000a0d0 -->0xc00000c338
[2] 0xc00000a0b8 [3] 0xc00000a0d0 -->0xc00000c340
[3] 0xc00000a0b8 [4] 0xc00000a0d0 -->0xc00000c348
[4] 0xc00000a0b8 [5] 0xc00000a0d0 -->0xc00000c350

k和v并不是每次分配新的变量,一直是一个变量。使用的时候要小心,要使用值传递

goroutine泄露

进程内存增加,到最后崩溃,按理说Golang自己管理内存,不存在内存泄露。但是大量使用goroutine,有的地方反复调用开启goroutine,之前的goroutine没有回收,就会造成goroutine泄露。

解决方法,在日志中定期打印goroutine数量,可以调用runtime.NumGoroutine() ,观察是否一直增加。

闭包

n := 0
f := func() int {
	n += 1
	fmt.Println(n)
	return n
}

f()
time.Sleep(time.Second)
go f()
time.Sleep(time.Second)

//输出
1
2

闭包,就是指匿名函数以及匿名函数引用的环境组合的实体。可以看到f函数对n做了修改,对函数来说,n就是本包的全局变量。

闭包与range带来的问题

arr := []int{1, 2, 3, 4, 5}
for k,v := range arr {
    go func(){
        fmt.Println(k, v)
    }()
}
// 输出结果
2 3
4 5
4 5
4 5
2 3


arr := []int{1, 2, 3, 4, 5}
for k,v := range arr {
    go func(key, value int){
        fmt.Println(key, value)
    }(k,v)
}
// 输出结果
1 2
0 1
3 4
2 3
4 5

第一个程序可以看到,结果没有达到预期,k和v是引用传递。

第二个程序使用函数参数显示的传入函数中,k和v是值传递。

对象滥用的后果

由于Golang会自己回收内存,因此不担心内存泄漏,可以用大胆地创建对象。但是会带来其他问题,比如网络句柄泄漏、文件句柄泄漏。

Golang会帮你释放对象,但是Golang不会帮你释放对象拥有的资源。

之所会出现这种情况,是因为在创建对象的时候不关心对象回收,于是不关注对象需要做什么清理动作,比如关闭描述符。

因此,在创建对象的时候,最好搞清楚对象占用了哪些资源,对象回收时需要做哪些动作。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值