亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

解鎖即可觀看《Go開發工程師》完整課程視頻

Go開發工程師

未來3-5年企業高性能項目不可替代的語言,從基礎到項目實戰再到重構,真正從入門到精通

【第1周】Go基礎知識入門
【第2周】容器,go編程思想
【第3周】Go并發編程和工程管理
【第4周】從0開始理解rpc和grpc
【第5周】grpc和protobuf進階
【第6周】 yapi文檔管理、gorm詳解
【第7周】gin快速入門
【第8周】用戶服務的grpc服務
【第9周】用戶服務的web服務
【第10周】服務注冊/發現、配置中心、負載均衡
【第11周】商品微服務的grpc服務
【第12周】 商品微服務的gin層和oss圖片服務
【第13周】庫存服務和分布式鎖
【第14周】訂單和購物車微服務
【第15周】 支付寶支付、用戶操作微服務、前后端聯調
【第16周】elasticsearch實現搜索微服務
【第17周】 分布式理論基礎、分布式事務解決方案
【第18周】 學習rocketmq實現冪等性機制等
【第19周】鏈路追蹤、限流、熔斷、降級
【第20周】api網關、部署
【第21周】開發規范和go基礎擴展
【第22周】設計模式和單元測試
【第23周】protoc插件開發、cobra命令行
【第24周】log日志包設計
【第25周】ast代碼生成工具開發
【第26周】三層代碼結構
【第27周】grpc服務封裝更方便的rpc服務
【第28周】深入grpc的服務注冊、負載均衡原理
【第29周】基于gin封裝api服務
【第30周】可觀測的終極解決方案
【第31周】系統監控核心
【第32周】用戶、商品服務重構
【第33周】訂單、庫存等服務重構
【第33+周】訂單服務重構、wire進行ioc控制
【第34周】通過k8s部署服務
【第34+周】devops和k8s
章節
問答
課簽
筆記
評論
占位
占位

go語句初探

    go語句和通道類型是Go語言的并發編程理念的最終體現。在第五章,我已經詳細介紹過了通道類型。相比之下,go語句在用法上要比通道簡單很多。與defer語句相同,go語句也可以攜帶一條表達式語句。注意,go語句的執行會很快結束,并不會對當前流程的進行造成阻塞或明顯的延遲。一個簡單的示例如下:

go fmt.Println("Go!")

    可以看到,go語句僅由一個關鍵字go和一條表達式語句構成。同樣的,go語句的執行與其攜帶的表達式語句的執行在時間上沒有必然聯系。這里能夠確定的僅僅是后者會在前者完成之后發生。在go語句被執行時,其攜帶的函數(也被稱為go函數)以及要傳給它的若干參數(如果有的話)會被封裝成一個實體(即Goroutine),并被放入到相應的待運行隊列中。Go語言的運行時系統會適時的從隊列中取出待運行的Goroutine并執行相應的函數調用操作。注意,對傳遞給這里的函數的那些參數的求值會在go語句被執行時進行。這一點也是與defer語句類似的。
  
    正是由于go函數的執行時間的不確定性,所以Go語言提供了很多方法來幫助我們協調它們的執行。其中最簡單粗暴的方法就是調用time.Sleep函數。請看下面的示例:

package main

import (
    "fmt"
)

func main() {
    go fmt.Println("Go!")
}  

    這樣一個命令源碼文件被運行時,標準輸出上不會有任何內容出現。因為還沒等Go語言運行時系統調度那個go函數執行,主函數main就已經執行完畢了。函數main的執行完畢意味著整個程序的執行的結束。因此,這個go函數根本就沒有執行的機會。
  
  但是,當我們在上述go語句的后面添加一條對time.Sleep函數的調用語句之后情況就會不同了:

package main

import (
    "fmt"
    "time"
)

func main() {
    go fmt.Println("Go!")
    time.Sleep(100 * time.Millisecond)
}

    語句time.Sleep(100 * time.Millisecond)會把main函數的執行結束時間向后延遲100毫秒。100毫秒雖短暫,但足夠go函數被調度執行的了。上述命令源碼文件在被運行時會如我們所愿地在標準輸出上打印出Go!

  
    另一個比較紳士的做法是在main函數的最后調用runtime.Gosched函數。相應的程序版本如下:

package main

import (
    "fmt"
    "runtime"
)

func main() {
    go fmt.Println("Go!")
    runtime.Gosched()
}

   runtime.Gosched函數的作用是讓當前正在運行的Goroutine(這里是運行main函數的那個Goroutine)暫時“休息”一下,而讓Go運行時系統轉去運行其它的Goroutine(這里是與go fmt.Println("Go!")對應并會封裝fmt.Println("Go!")的那個Goroutine)。如此一來,我們就更加精細地控制了對幾個Goroutine的運行的調度。
  
    當然,我們還有其它方法可以滿足上述需求。并且,如果我們需要去左右更多的Goroutine的運行時機的話,下面這種方法也許更合適一些。請看代碼:

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    wg.Add(3)
    go func() {
        fmt.Println("Go!")
        wg.Done()
    }()
    go func() {
        fmt.Println("Go!")
        wg.Done()
    }()
    go func() {
        fmt.Println("Go!")
        wg.Done()
    }()
    wg.Wait()
}

    sync.WaitGroup類型有三個方法可用——Add、DoneWait。Add會使其所屬值的一個內置整數得到相應增加,Done會使那個整數減1,而Wait方法會使當前Goroutine(這里是運行main函數的那個Goroutine)阻塞直到那個整數為0。這下你應該明白上面這個示例所采用的方法了。我們在main函數中啟用了三個Goroutine來封裝三個go函數。每個匿名函數的最后都調用了wg.Done方法,并以此表達當前的go函數會立即執行結束的情況。當這三個go函數都調用過wg.Done函數之后,處于main函數最后的那條wg.Wait()語句的阻塞作用將會消失,main函數的執行將立即結束。
  
    與go語句、go函數以及承載其運行的Goroutine相關的話題其實還有很多。不過由于篇幅等原因,我的講述就先到此為止。如果大家對這方面的內容感興趣的話請參看《Go并發編程實戰》這本書。這里面會有非常詳盡的介紹。

任務

    在命令源碼文件index.go中的main函數中,我編寫了三條go語句。其中的go函數會分別向標準輸出打印一個整數。我希望打印的最終結果是

1
2
3

    請你對其中的代碼做適當的修改來滿足這個需求。

?不會了怎么辦

修改后的文件內容可以是:

package main

import (
    "fmt"
)

func main() {
    ch1 := make(chan int, 1)
    ch2 := make(chan int, 1)
    ch3 := make(chan int, 3)
    go func() {
        fmt.Println("1")
        ch1 <- 1
    }()
    go func() {
        <-ch1
        fmt.Println("2")
        ch2 <- 2
    }()
    go func() {
        <-ch2
        fmt.Println("3")
        ch3 <- 3
    }()
    <-ch3
}

 

||

提問題

寫筆記

公開筆記
提交
||

請驗證,完成請求

由于請求次數過多,請先驗證,完成再次請求

加群二維碼

打開微信掃碼自動綁定

您還未綁定服務號

綁定后可得到

  • · 粉絲專屬優惠福利
  • · 大咖直播交流干貨
  • · 課程更新,問題答復提醒
  • · 賬號支付安全提醒

收藏課程后,能更快找到我哦~

使用 Ctrl+D 可將課程添加到書簽

邀請您關注公眾號
關注后,及時獲悉本課程動態

舉報

0/150
提交
取消
全部 精華 我要發布
全部 我要發布
最熱 最新
只看我的

手記推薦

更多

本次提問將花費2個積分

你的積分不足,無法發表

為什么扣積分?

本次提問將花費2個積分

繼續發表請點擊 "確定"

為什么扣積分?