文章目錄
- Goroutines(Go的線程機制)
- Channels(管道)
面向Java開發人員的GO編程
英文原文在此www.nada.kth.se/~snilsson/go_for_java_programmers
譯文同步至www.waylau.com
http://bbs.gocn.im/thread-89-1-1.html
=================接上文,以下本文====================
Panic and recover(恐懼和恢複)
panic
(恐慌)是一個執行階段錯誤,展開goroutine的堆棧,一路運行任何遞延的功能,然後停止程式。恐慌與Java異常相似,但只適用於運行時的錯誤,如一個nil
指標或試圖索引數組越界。 Go程式使用內建的error
類型(詳見上文)為了表示如檔案結束等事件。
可以使用內建的recover
(恢複),重新獲得控制權的恐慌的goroutine和恢複正常運行。呼叫recover
停止展開,並返回傳入的參數panic
。因為只有啟動並執行未展開代碼,內部含有延遲函數,recover
只在內遞延的函數有效。如果的goroutine是沒有恐慌,recover
返回nil
。
Go的線程機制和管道Goroutines(Go的線程機制)
Go允許用go
開啟一個新的執行線程--goroutine。它運行在不同的,新建立的的goroutine中。在一個程式中的所有goroutine共用相同的地址空間。
Goroutines是輕量級的,只佔用比堆棧分配多一點的空間。堆棧開始小和成長的分配和釋放堆(heap)的要求。內部goroutines像進行了複用多個作業系統線程的協程。您不必擔心這些細節。
go list.Sort() // Run list.Sort in parallel; don’t wait for it.
Go處理文字的函數,可以作為結束,在處理go
時很強大
func Publish(text string, delay time.Duration) { go func() { time.Sleep(delay) fmt.Println(text) }() // Note the parentheses. We must call the function.}
變數text
和delay
在周圍函數和函數文字之間共用;只要它們都可以訪問,它們就存在。
Channels(管道)
管道通過指定的元素類型的值來提供兩個goroutine同步執行和溝通的機制。 <-
操作符指定通道的方向,發送或接收。如無任何指示方向時,通道是雙向的。
chan T // can be used to send and receive values of type Tchan<- float64 // can only be used to send float64s<-chan int // can only be used to receive ints
管道是一個參考型別,用make分配。
ic := make(chan int) // unbuffered channel of intswc := make(chan *Work, 10) // buffered channel of pointers to Work
使用<-
作為一個二元操作符來在管道上發送值。當在管道上接收一個值時,把它作為一元運算子。
ic <- 3 // Send 3 on the channel.work := <-wc // Receive a pointer to Work from the channel.
如果管道是無緩衝,那麼寄件者阻塞,直到接收器接收到值。如果管道有一個緩衝區,寄件者阻塞,直到該值已被複製到緩衝區。如果緩衝區已滿,這意味著等待,直到一些接收器中檢索到值。接收器被阻塞,直到有資料接收。
並發 (樣本)
最後我們用一個例子來說明如何散落的內容拼起來。這是一個伺服器通過管道來接受的Work
請求的例子。每個請求都在一個單獨的goroutine運行。Work
結構本身包含了一個管道,用於返回一個結果。
package serverimport "log"// New creates a new server that accepts Work requests// through the req channel.func New() (req chan<- *Work) { wc := make(chan *Work) go serve(wc) return wc}type Work struct { Op func(int, int) int A, B int Reply chan int // Server sends result on this channel.}func serve(wc <-chan *Work) { for w := range wc { go safelyDo(w) }}func safelyDo(w *Work) { // Regain control of panicking goroutine to avoid // killing the other executing goroutines. defer func() { if err := recover(); err != nil { log.Println("work failed:", err) } }() do(w)}func do(w *Work) { w.Reply <- w.Op(w.A, w.B)}
server.go
下面展示如何使用:
package server_testimport ( server "." "fmt")func main() { s := server.New() divideByZero := &server.Work{ Op: func(a, b int) int { return a / b }, A: 100, B: 0, Reply: make(chan int), } s <- divideByZero add := &server.Work{ Op: func(a, b int) int { return a + b }, A: 100, B: 200, Reply: make(chan int), } s <- add fmt.Println(<-add.Reply) // Output: 300}
example_test.go
並發編程是一個大主題,Java和Go的方法是完全不同的。要想充分體驗到並發編程的樂趣,看這篇Share Memory by Communicating(《通過溝通共用記憶體》)
Stefan Nilsson
該文基於相似的文章 《面向C++的GO編程》
=================全文完畢。轉載註明出處=====================
全文下載http://download.csdn.net/detail/kkkloveyou/4991168
2013-1-13