導語
Go語言(也稱為Golang)是google在2009年推出的一種編譯型編程語言。相對于大多數語言,golang具有編寫并發或網絡交互簡單、豐富的數據類型、編譯快等特點,比較適合于高性能、高并發場景。本文主要基于筆者的親身實踐和總結,介紹golang的一些特性,重點介紹并發的實現和使用,希望能引發讀者一些啟發或興趣。
1、Golang簡介
Go語言(也稱為Golang)是google在2009年推出的一種編譯型編程語言。相對于大多數語言,golang具有編寫并發或網絡交互簡單、豐富的數據類型、編譯快等特點,比較適合于高性能、高并發場景。2015年度的TIOBE指數計算機語言份額排名中,golang排在60+名,19年7月已上升到16名。
筆者曾于15年上半年在2個實際項目中引入golang 1.3,代碼量大概在3000行左右,最大的體會是并發編程入門容易。本文將以1.3來介紹,不過golang團隊更新太快,19年最新版本已到了1.12,不過核心設計思想與1.3并無大差異。
眾所周知,曾經在很長一段時間里,google保持著一個傳統,允許員工擁有20%自由時間來開發實驗性項目,可惜現在該制度已經廢棄。golang正是由一個強大團隊利用這20%時間開發的。這里有必要介紹一下該團隊的核心成員,個個來頭不小,都是計算機領域大神級人物。最大牌的當屬B和C語言設計者、Unix和Plan 9創始人、1983年圖靈獎獲得者Ken Thompson,其以70+歲高齡,不知道在golang實際開發中撰了多少代碼......另外,這份名單中還包括了Unix核心成員Rob Pike、java HotSpot虛擬機和js v8引擎的開發者Robert Griesemer、Memcached作者Brad Fitzpatrick,等等。
OK,進入正題,筆者結合個人整理和思考,依次介紹golang幾個值得一說的特性和精髓,如果讀者能從中受到某些啟發,就足夠了。
2、并發編程
通過實踐,筆者認為golang在并發編程方面比絕大多數語言要簡潔不少,這一點是其最大亮點之一,也是其在未來進入高并發高性能場景的重要籌碼。
不同于傳統的多進程或多線程,golang的并發執行單元是一種稱為goroutine的協程。協程這個概念已被引入到不少語言中,比如golang、python、lua等。協程經常被理解為輕量級線程,一個線程可以包含多個協程,共享堆不共享棧。協程間一般由應用程序顯式實現調度,上下文切換無需下到內核層,高效不少。協程間一般不做同步通訊,而golang中實現協程間通訊有兩種:1)共享內存型,即使用全局變量+mutex鎖來實現數據共享;2)消息傳遞型,即使用一種獨有的channel機制進行異步通訊。
由于在共享數據場景中會用到鎖,再加上GC,其并發性能有時不如異步復用IO模型,因此相對于大多數語言來說,golang的并發編程簡單比并發性能更具賣點。
2.1、示例說明
下面是一段用golang寫的并發程序:
package main
import {
"fmt"
"runtime"
"time"
}
var MULTICORE int
func main() {
MULTICORE = runtime.NumCPU() //計算出本地的cpu核總數
//指定MULTICORE個核來運行
//這里沒有設置cpu親和性,所以各個線程會在任意cpu核上跑,同一個線程也可能會不斷跳到不同核上運行
runtime.GOMAXPROCS(MULTICORE)
// 啟動MULTICORE個goroutine來執行test()
for i := 0; i < MULTICORE; i++ {
go test()
}
// sleep 10s是為了讓主進程等待所有goroutine都運行退出
time.Sleep(10*time.Second)
}
func test() {
for i := 0; i < 10; i++ {
fmt.Printf("test\n")
}
}
可以看出,啟動一個goroutine很容易,只需要在(匿名)函數前面加個go關鍵字就行,還能夠指定運行核數,以期充分利用機器的計算能力。
2.2、底層實現
golang相較于傳統語言,為了更好適應現代多核、高并發場景,獨創了自己的協程模型,采用m:n模型,即m個gorountine(簡稱為G)映射到n個用戶態上下文(簡稱為P)上,一個P向上維護多個G組成的一個隊列,一個P向下與一個內核態工作線程(簡稱為M)相綁定。
完整文章見:https://github.com/star2478/golang-wiki/wiki/%E6%B5%85%E8%B0%88Go%E8%AF%AD%E8%A8%80