91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Go?select使用與底層原理是什么

發布時間:2022-08-01 11:01:50 來源:億速云 閱讀:131 作者:iii 欄目:開發技術

本篇內容主要講解“Go select使用與底層原理是什么”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Go select使用與底層原理是什么”吧!

1. select的使用

select 是 Go 提供的 IO 多路復用機制,可以用多個 case 同時監聽多個 channl 的讀寫狀態:

  • case: 可以監聽 channl 的讀寫信號

  • default:聲明默認操作,有該字段的 select 不會阻塞

select {
case chan <-:
    // TODO
case <- chan:
    // TODO
default:
    // TODO
}

2. 底層原理

  • 每一個 case 對應的 channl 都會被封裝到一個結構體中;

  • 當第一次執行到 select 時,會鎖住所有的 channl 并且,打亂 case 結構體的順序;

  • 按照打亂的順序遍歷,如果有就緒的信號,就直接走對應 case 的代碼段,之后跳出 select;

  • 如果沒有就緒的代碼段,但是有 default 字段,那就走 default 的代碼段,之后跳出 select;

  • 如果沒有 default,那就將當前 goroutine 加入所有 channl 的對應等待隊列;

  • 當某一個等待隊列就緒時,再次鎖住所有的 channl,遍歷一遍,將所有等待隊列中的 goroutine 取出,之后執行就緒的代碼段,跳出select。

3. 數據結構

每一個 case 對應的數據結構如下:

type scase struct {
    c           *hchan         // chan
    elem        unsafe.Pointer // 讀或者寫的緩沖區地址
    kind        uint16   //case語句的類型,是default、傳值寫數據(channel <-) 還是  取值讀數據(<- channel)
    pc          uintptr // race pc (for race detector / msan)
    releasetime int64
}

4. 幾種常見 case

學習了 select 的使用與原理,我們就能更輕松地分辨不同情況下的輸出情況了。

case 1

package main

import (
  "fmt"
  "time"
)

func main() {
  chan1 := make(chan int)
  chan2 := make(chan int)
  go func() {
    chan1 <- 1
    time.Sleep(5 * time.Second)
  }()
  go func() {
    chan2 <- 1
    time.Sleep(5 * time.Second)
  }()
  select {
    case <- chan1:
      fmt.Println("chan1")
    case <- chan2:
      fmt.Println("chan2")
    default:
      fmt.Println("default")
  }
}

三種輸出都有可能。

case2

package main

import (
  "fmt"
  "time"
)
func main() {
  chan1 := make(chan int)
  chan2 := make(chan int)
  
  select {
    case <- chan1:
      fmt.Println("chan1")
    case <- chan2:
      fmt.Println("chan2")
  }
  fmt.Println("main exit.")
}

上述程序會一直阻塞。

case3

package main

import (
  "fmt"
)

func main() {
  chan1 := make(chan int)
  chan2 := make(chan int)
  
  go func() {
    close(chan1)
  }()
  go func() {
    close(chan2)
  }()
  select {
    case <- chan1:
      fmt.Println("chan1")
    case <- chan2:
      fmt.Println("chan2")
  }
  fmt.Println("main exit.")
}

隨機執行1或者2.

case4

package main

func main() {
  select {
  }
}

對于空的 select 語句,程序會被阻塞,確切的說是當前協程被阻塞,同時 Go 自帶死鎖檢測機制,當發現當前協程再也沒有機會被喚醒時,則會發生 panic。所以上述程序會 panic。

到此,相信大家對“Go select使用與底層原理是什么”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

察哈| 江口县| 乳山市| 东辽县| 临海市| 福鼎市| 新宁县| 应用必备| 尖扎县| 定陶县| 焉耆| 隆子县| 堆龙德庆县| 鲁甸县| 安义县| 合江县| 北安市| 潍坊市| 北海市| 白朗县| 哈密市| 葫芦岛市| 赤峰市| 商都县| 大化| 长武县| 宾川县| 灌阳县| 张家港市| 乌兰浩特市| 黑山县| 大同县| 永宁县| 阳谷县| 庆阳市| 龙山县| 富川| 浠水县| 大化| 肥东县| 六盘水市|