Golang 介绍及踩坑系列之一

Chang · · 4245 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

golang是一门简明,强劲,安全的编程语言。我喜欢他支持指针同时提供了各种安全机制减低烧脑度。比如:

func getIntegerAddress() *int{
    a:=10
    return &a
}

这玩意放在c++里边你会错到欲仙欲死,可是用golang这就是一个正常实现(虽然有点二)。而且go的performance不差。

如果你跟我一样是个非常弱逼的c/c++程序员,看到这里的你应该已经比较激动了。

别急,还有些其他牛逼闪闪的东西呢。

channel和goroutine。

你制造了个东西,你知道有人会处理它,可是你不知道具体是谁。可能你制造这玩意特别快,但是处理的人比较慢。一个不太形象的比喻是,你可以呸呸呸呸瞬间吐出十口痰,然后清洁卫生的大妈要一把诅咒你全家还有你未出生的孩子的菊花同时用各种工具去清理这些玩意。我们可以想象,一位大妈是没法很快搞定你的十口浓痰的,我们可能需要n位大妈一起合作。如果是别的什么语言,咱们可能就要生成一个大妈的worker pool,并且像个办法把代表这些浓痰的memeory共享出来给大妈们。

如果用golang这个骚骚的工具,我们可以写出这样的代码来:

package main

import "time"

var phlegms = make(chan int) //这里存所有吐得痰

func spit(phlegm int) { //吐痰函数
	phlegms <- phlegm
}

func cleanItUp() {//大妈函数
	for {
		select {
	        case phlegm := <-phlegms:
		     println("I cleaned ", phlegm)
                }
	}
}

func main() {
	for i := 0; i < 1000; i++ {
		go spit(i)//连吐1000口痰
	}
	for i := 0; i < 10; i++ {
		go cleanItUp()//生成10个大妈
	}

	<-time.After(5 * time.Second)
}

跟我一样的concurrency苦手们,看到这里是不是已经按捺不住要跟golang来一发了?

是时候用几个golang的小坑适当的平衡一下你们的热情了,否则可能每个人都要雇佣几位大妈帮你们cleanup一下你们的屏幕。

func httpHandler() {
	resultCh := make(chan bool)
	go func() {
		defer close(resultCh)
		resultCh <- someTimeConsumingRPC()
	}()
	select {
	case result := <-resultCh:
		println(result)
	case <-time.After(1 * time.Second):
		println("shit")
	}
}

我们假设someTimeConsumingRPC() 是一个不太稳定的调用,有时候它超过一秒钟才返回。那么恭喜你,你的http service将会:内存泄漏!

原因是:goroutine不能强制杀掉!当超过了一秒钟,没人读resultCh的情况下,写result的goroutine永远无法完成!每个goroutine占用8k以上内存,当你这样卡死的goroutine多了,你的内存占用量和goroutine总数就会居高不下,并且最终导致你的服务器内存不足,服务崩溃。

可能有的老湿想跳出来说:楼主sb。给resultCh一个buffer不就完事了么?是的,这样做这个例子就行得通了,但是buffered channel是不是万能的呢?我们再看一个例子

package main

import "fmt"

func httpHandler() {
	errCh := make(chan error, 1)
	resultCh := make(chan int, 1)
	go func() {
		defer close(errCh)
		defer close(resultCh)
		errCh <- fmt.Errorf("shit")
	}()
	select {
	case <-errCh:
	case <-resultCh:
		println("this shall not happen dude!")
	}
}

func main() {
	for i := 0; i < 1000000; i++ {
		httpHandler()
	}
}

这个例子特别有意思。运行100万次,我自己的mbp上面出现了不到10次"this shall not happen dude!"的log。

聪明的你,这是为什么呢?


有疑问加站长微信联系(非本文作者)

本文来自:知乎专栏

感谢作者:Chang

查看原文:Golang 介绍及踩坑系列之一

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

4245 次点击  
加入收藏 微博
3 回复  |  直到 2019-02-11 11:31:06
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传