go version go1.11 windows/amd64
本文爲閱讀Go語言中文官網的規則說明書(https://golang.google.cn/ref/spec)而做的筆記,介紹Go語言的 Go語句(Go statements)。
Go語句 用於將一個 函數調用 作爲一個 獨立的併發線程(an independent concurrent thread of control) 或者 叫做 Go例程(goroutine) 來執行——新建一個Go例程、立即執行,這個 新的Go例程 和 之前的程序 在同一個地址空間。
疑問,Go程序運行後——從main()函數進入——是運行一個 進程 吧?這個進程有 主線程 吧?Go例程 就是 建立了一個新的線程,和 主線程 併發 運行——在僅有一個CPU時交替使用CPU資源,在有多個CPU時,是否在不同的CPU上運行?後者是並行吧?那麼,這裏的併發,是否包含了並行?Go例程裏面 還可以 啓動新的Go例程嗎?如果可以,允許的最大層級是怎樣的?對於Go例程和創建它的程序共享地址空間這個問題,還不是很清楚,有什麼用呢?Go例程可以使用原程序中的 變量、常量 等——讀和寫?
GoStmt = "go" Expression .
上面是Go語句的 語法,其中的 表達式(Expression)必須是 函數 或 方法調用,並且不能用圓括號括起來(是指Expression不能被括起來吧?把go Expression用一起括起來應該是可以的)。
雖然Expression可以是 法術 或 方法調用,但是,對於內建函數的使用是有限制的(Expression statements),下面這些 內建函數 不能出現在 語句上下文——包括Go語句 中:
append cap complex imag len make new real unsafe.Alignof unsafe.Offsetof unsafe.Sizeof
說明,append不可以,但copy可以;複數的三個內建函數都不可以;獲取長度、容量的函數不可以;new、make不可以;還有unsafe包中的幾個函數——暫不清楚它們的用處。
在Go例程中,函數的值和參數 和 正常調用 一樣被求值,但和正常調用不同的是,程序的執行 不會 等到被調用的函數完成,相反,程序開始在一個新的Go例程中獨立地執行。
在函數 終止 時,它的Go例程也會終止。如果函數有返回值,這些返回值會在函數完成時被 丟棄。
解讀,根據上面的信息,Go例程 有什麼用途呢?可以用在什麼地方呢?耗時操作?Web服務器 的一個用戶請求處理程序?一個程序 可以新建多少Go例程呢?和計算機的資源多少有關係?新建的Go例程只能在本機運行嗎?可以指派到其它計算機上執行——實現分佈式執行?一臺電腦的程序 被 放到 另一臺電腦執行,感覺像是 控制了另一臺電腦?Go語言本身是否支持這樣的操作?不然的話,一定會有其它軟件實現方式的。畢竟那麼多病毒程序都已經實現了。
官文示例:
go Server()
go func(ch chan<- bool) { for { sleep(10); ch <- true }} (c) // 注意這裏的 (c),這是函數調用 的 括號 及 參數
上面的官文示例就太簡單了,下面給出一個複雜一些的——來自網絡:
通過 篩選法 尋找素數——這個程序俺大致看懂了,晚點會徹底看懂它。
原文鏈接不知道在哪裏了,網上可以搜索到類似的鏈接,比如,http://www.yankay.com/go-clear-concurreny/ (Go-簡潔的併發),
package main import ( "fmt" ) // Send the sequence 2, 3, 4, ... to channel 'ch' func generate(ch chan<- int) { for i := 2; ; i++ { ch <- i // Send 'i' to channel 'ch' } } // Copy the values from channel 'src' to channel 'dst', // removing those divisible by 'prime'. func filter(src <-chan int, dst chan<- int, prime int) { for i := range src { // Loop over values received from 'src' if i%prime != 0 { dst <- i // Send 'i' to channel 'dst' } } } // The prime sieve: Daisy-chain filter processes together. func sieve() { ch := make(chan int) // Create a new channel. go generate(ch) // Start generate() as a subprocess. for { prime := <-ch fmt.Print(prime, "\n") ch1 := make(chan int) go filter(ch, ch1, prime) ch = ch1 } } func main() { sieve() }
參考鏈接
2.Go-簡潔的併發
後記
好了,很清楚Go例程是什麼了,但是還有一些疑問需要搞清楚!
另外,Go語言 內置 的併發特性有什麼好處呢?好需要更多實踐來體會纔是!
在官文Effective Go中有一節名爲Concurrency,稍候會好好看看,有需要,再補充此文——估計不會的了。
學習編程語言,就是爲了 解決問題,要親自寫代碼去解決問題。
比如上面的尋找素數的問題,若是自己來寫,用Go語言來寫,會寫成什麼樣呢?估計是不會用Go例程的!可先行者們知道用Go例程了,看來自己的Go學習之路還有些漫長呢!
只有繼續投入精力了!
還有Go開發者可以使用Go語言開發區塊鏈程序了,感覺好高級啊!
什麼時候自己也可以寫點 高級的程序呢?
從上月末開始學(接觸)Go開發,直到現在都還沒 用Go寫一個Web服務器出來,方式方法&行動力都存在嚴重問題啊!
需反省,改進!