一 Golang对协程的支持
Go语言从语言层面原生提供了协程支持,即 goroutine,执行goroutine只需极少的栈内存(大概是4~5KB),所以Go可以轻松的运行多个并发任务。  
Go中以关键字 go 开启协程:
func say(s string) {
    for i := 0; i < 3; i++ {
        fmt.Println(s)
    }
}
func main() {
    go say("Go")                        // 以协程方式执行say函数
    say("noGo")                            // 以普通方式执行say函数
    time.Sleep(5 * time.Second)         // 睡眠5秒:防止协程未执行完毕,主程序退出
}
上述的程序的打印结果并不是按照顺序的,因为go关键字开启了协程,两个say函数并不是在一个控制流中!
二 goroutine使用案例
2.1 同时执行两件事
func running() {
    var times int
    for {
        times++
        fmt.Println("tick:", times)
        time.Sleep(time.Second)
    }
}
func main() {
    go running()
    var input string
    fmt.Scanln(&input)
}
命令行会不断地输出 tick,同时可以使用 fmt.Scanln() 接受用户输入。两个环节可以同时进行,直到按 Enter键时将输入的内容写入 input变量中井返回,
整个程序终止。
2.2 一道基础面试题
示例一:
for i := 1; i <= 10; i++ {
    go func(){
        fmt.Println(i)        // 全部打印11:因为开启协程也会耗时,协程没有准备好,循环已经走完
    }()
}
time.Sleep(time.Second)
示例二:
    for i := 1; i <= 10; i++ {
        go func(i int){
            fmt.Println(i)        // 打印无规律数字
        }(i)
    }
    time.Sleep(time.Second)
三 常用API
3.1 GOMAXPROCS() 多核利用
goroutine相关API位于 runtime 包。  
如果Go程序要运行在多核上,则可以如下操作,此时可以实现程序的并行执行:
    cpuNum := runtime.NumCPU()                //获取当前系统的CPU核心数
    runtime.GOMAXPROCS(cpuNum)                //Go中可以轻松控制使用核心数
贴士:在Go1.5之后,程序已经默认运行在多核上,无需上述设置
3.2 Gosched() 让出时间片
runtime.Gosched():用于让出CPU时间片,即让出当前协程的执行权限,调度器可以去安排其他等待的任务运行。示例如下: 
func main(){
    for i := 1; i <= 10; i++ {
        go func(i int){
            if i == 5 {
                runtime.Gosched()    // 协程让出,但并不代表不执行,而是 5永远不会第一输出
            }
            fmt.Println(i)        // 打印一组无规律数字
        }(i)
    }
    time.Sleep(time.Second)
}
贴士:可以理解为接力赛跑:A跑了一段遇到了Gosched接力给B。
3.3 Goexit() 终止当前协程
runtime.Goexit():用于立即终止当前协程运行,调度器会确保所有已注册defer延迟调用被执行。  
func main(){
    for i := 1; i <= 5; i++ {
        defer fmt.Println("defer ", i)
        go func(i int){
            if i == 3 {
                runtime.Goexit()
            }
            fmt.Println(i)
        }(i)
    }
    time.Sleep(time.Second)
}
输出的结果类似于:
4
2
5
1
defer  5
defer  4
defer  3
defer  2
defer  1