<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                > # channel - 長度和容量 ~~~ package main import "fmt" func main() { ch := make(chan struct{}, 3) ch <- struct{}{} fmt.Println(len(ch)) //輸出1 fmt.Println(cap(ch)) //輸出3 } ~~~ - 限制發送/接收類型 ~~~ chan T // 可以接收和發送類型為 T 的數據 chan<- T // 只可以用來發送 T 類型的數據 <-chan T // 只可以用來接收 T 類型的數據 ~~~ > # 底層數據結構 ``` type hchan struct { qcount uint // 通道中的當前元素個數 dataqsiz uint // 緩沖區的大小 (無緩沖時為0) buf unsafe.Pointer // *環形緩沖區* 指向緩沖區的指針 ,緩沖區通過這個指針來存儲數據,已經發送但還未被接收的數據 elemsize uint16 // 單個元素的大小(如果通道是 `chan int` 類型,那么每個元素就是一個 `int`,`elemsize` 表示 `int` 類型的字節大小。) closed uint32 // 標識 channel 是否已關閉 (0 表示未關閉,1 表示已關閉) timer *timer //用于處理與該通道相關的超時操作 elemtype *_type //指向類型描述符的指針,它包含了通道中傳輸數據類型的所有信息 sendx uint // 下一個要發送元素的位置 recvx uint // 下一個要接收元素的位置 (每次讀取數據后,`recvx` 都會遞增,當到達緩沖區末尾時,`recvx` 會重置為 0,形成環形讀取操作) recvq waitq // 等待接收數據的 goroutine 隊列 sendq waitq // 等待發送數據的 goroutine 隊列 lock mutex // 互斥鎖,用于保護 channel 的操作 } ``` > # 發送和接收數據的本質 - 向 channel 發送值類型會拷貝, 發送引用類型拷貝的是引用 ~~~ package main import "fmt" func main() { ch := make(chan []int, 1) s := make([]int, 1) s[0] = 1 ch <- s s[0] = 2 fmt.Println(<-ch) //輸出2 } ~~~ > # 操作 nil channel, close channel, 正常 channel | 操作 | nil channel | close channel | 正常 channel | | --- | --- |--- |--- | | close | panic: close of nil channel | panic: close of closed channel | 正常關閉| | 讀操作 | fatal error: all goroutines are asleep - deadlock! | 有未接收的值可以正常讀, 沒有的話讀到對應類型的零值| 阻塞/正常讀數據| | 寫操作 | fatal error: all goroutines are asleep - deadlock! | panic: send on closed channel | 阻塞/正常寫數據| > # 使用 select 來多路復用 channel - **隨機選擇**:當多個 `channel` 同時滿足條件時,`select` 會隨機選擇一個執行。 - **默認分支**:可以在 `select` 中添加 `default` 分支,當所有的 `channel` 都沒有數據時,`select` 可以立即執行 `default` 分支而不阻塞。 ~~~ package main import ( "fmt" "time" ) func main() { ch1 := make(chan struct{}) ch2 := make(chan struct{}) go func() { ch1 <- struct{}{} }() go func() { ch2 <- struct{}{} }() select { case <-ch1: fmt.Println("ch1") case <-ch2: fmt.Println("ch2") case <-time.After(2 * time.Second): fmt.Println("超時") default: fmt.Println("default") time.Sleep(1 * time.Second) } } ~~~ > # range channel ``` package main import ( "fmt" ) func main() { ch := make(chan int) go func() { close(ch) }() //如果通道不被關閉,range 將會一直等待新的數據,不會自動退出循環 for v := range ch { fmt.Println(v) } fmt.Println("Done") } ``` > # 讀取關閉的channel ~~~ package main import "fmt" func main() { ch := make(chan int, 2) ch <- 1 ch <- 2 close(ch) v, ok := <-ch fmt.Println(v, ok) //1 true v, ok = <-ch fmt.Println(v, ok) //2 true v, ok = <-ch fmt.Println(v, ok) //0 false //沒數據了,返回對應類型的零值和false } ~~~ > # 如何優雅的關閉 channel - v, ok := <-ch 取值的時候加判斷, 關閉的channel, v 返回對應類型的零值, ok 返回 false。用這種方式去判斷channel 是否關閉有副作用, 會讀出channel里的元素 - [如何優雅的關閉Go Channel](https://www.ulovecode.com/2020/07/14/Go/Golang%E8%AF%91%E6%96%87/%E5%A6%82%E4%BD%95%E4%BC%98%E9%9B%85%E5%85%B3%E9%97%ADGo-Channel/) - 多生產者多消費者例子(關閉原則:不要在消費端關閉channel,不要在生產端有多個的并行時候執行關閉操作) ~~~ package main import ( "fmt" "sync" "time" ) func main() { ch := make(chan int, 1024) chClose := make(chan struct{}) var wg sync.WaitGroup wg.Add(10) for i := 0; i < 10; i++ { go func(num int) { for { select { case <-chClose: fmt.Println("發送關閉1", num) return default: } select { case <-chClose: fmt.Println("發送關閉1", num) return case ch <- num: } } }(i) } for i := 0; i < 10; i++ { go func(num int) { for { select { case <-chClose: fmt.Println("接收關閉1", num) wg.Done() return default: } select { case <-chClose: fmt.Println("接收關閉2", num) wg.Done() return case v, _ := <-ch: _ = v } } }(i) } time.Sleep(time.Second * 3) chClose <- struct{}{} close(chClose) wg.Wait() } ~~~ > # 交替打印 - 可以通過runtime.GOMAXPROCS設置處理器數量為1, runtime.Gosched() 讓出當前調度 ~~~ package main import ( "fmt" "time" ) func main() { //不能是 ch := make(chan struct{}, 1), 協程調度是隨機的, 如果緩存為1,會出現某個協程被執行多次 ch := make(chan struct{}, 0) go func() { for { <-ch fmt.Println(1) ch <- struct{}{} } }() go func() { for { <-ch fmt.Println(2) ch <- struct{}{} } }() ch <- struct{}{} time.Sleep(time.Hour) } ~~~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看