1. 程式人生 > >Golang協程機制以及異常處理

Golang協程機制以及異常處理

golang之所有好用,是因為其將以前程式設計中常用的而且晦澀難用的非同步任務以及訊號機制,以傻瓜式的語法給封裝了一層。接觸了golang已經有一段時間了,現在回頭再看一下golang的協程機制,順便做個總結。

一. 協程機制

系統核心可以理解成一個經驗豐富的管家,能把以前無系統下的各種任務(包括各種非同步任務同步任務)給處理的很得當。其基本思想就是建造了程序物件,讓cpu在多程序下來回切換,卻又讓程序無法察覺。這種解決方案徹底將應用層程式設計給分離了出來。但是後來隨著任務量的增加,人們發現頻繁的切換程序會造成很多額外的消耗(記憶體表等程序資源的切換消耗),而隨著任務量增加,這種問題尤為突出。於是人們又發明了執行緒(Thread),執行緒是基於程序下的多工,多執行緒降低了因為系統的程序量,多執行緒可以共用程序資源,但是多執行緒的任務切換也離不開核心的上下文切換以及cpu的暫存器內容切換。

golang基於以上計算機成果,線上程上創造了非同步任務的實現方法---協程

協程組成:

1. M(應用層排程器):進行協程間的任務排程

2. P(系統執行緒):決定了最大併發執行任務數,通過GOMAXPROCS引數控制執行緒數

3. G(協程):獨立執行的基本單位

基本思想:排程器執行時會建立執行緒池,並把協程放到執行緒上執行,待協程到了觸發點(協程退出,使用channel、系統呼叫等休眠)時,排程器會把原有協程取出,再把待執行的協程放到執行緒裡面執行。可以看到,這是在應用層實現了核心的任務切換功能;

資源消耗對比: 

執行緒:2M棧,需要核心參與排程

協程:2K棧,不需要核心cpu進行任務排程

因此,可以說golang的協程非常輕量

二. 異常處理

1. golang沒有java和php的try catch機制。其提議通過多返回值的形式丟擲錯誤;

2. 但同時又支援通過defer,recover來處理panic錯誤(若不捕捉怎程序異常退出),如:

package main

import(
	"fmt"
	"time"
)

func test(){
	defer func(){ // 必須要先宣告defer,否則不能捕獲到panic異常
		if err:=recover();err!=nil{
			fmt.Println(err) // 這裡的err其實就是panic傳入的內容,55
		}
	}()
	panic("panic")
}

func main(){

	go test()
	for{
		fmt.Println("1")
		time.Sleep(time.Duration(1)*time.Second)
	}
}
輸出:
1
panic
1
1