亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解go語言判斷管道是否關(guān)閉的常見誤區(qū)

 更新時間:2023年10月09日 10:29:42   作者:林欣快滾去學習  
這篇文章主要想和大家一起探討一下在Go語言中,我們是否可以使用讀取管道時的第二個返回值來判斷管道是否關(guān)閉,文中的示例代碼講解詳細,有興趣的可以了解下

前言

本文是探討的是"在Go語言中,我們是否可以使用讀取管道時的第二個返回值來判斷管道是否關(guān)閉?"

樣例

在Go語言中,我們是否可以使用讀取管道時的第二個返回值來判斷管道是否關(guān)閉? 可以看下面的代碼

package main
import "fmt"
func main() {
    // 創(chuàng)建一個整型管道
    ch := make(chan int)
    // 啟動一個協(xié)程往管道發(fā)送數(shù)據(jù)
    go func() {
        for i := 0; i < 5; i++ {
            ch <- i
        }
        // 關(guān)閉管道
        close(ch)
    }()
    // 能否判斷管道是否關(guān)閉?
    if _, ok := <-ch; !ok {
        fmt.Println("管道已關(guān)閉")
    }
}

探討 管道的數(shù)據(jù)結(jié)構(gòu)

在探討這個問題之前,我們先來了解一下管道的數(shù)據(jù)結(jié)構(gòu),從go的源碼,我們可以知道,管道是被定義為一個名為hchan的結(jié)構(gòu)體:

type hchan struct {
    qcount   uint           //當前隊列中剩余的元素個數(shù)
    dataqsiz uint           // 環(huán)形隊列管道容積
    buf      unsafe.Pointer // 環(huán)形隊列指針
    elemsize uint16         // 元素大小
    closed   uint32         // 標識管道關(guān)閉的狀態(tài)
    elemtype *_type         // 元素類型
    recvq    waitq          // 等待的讀元素的協(xié)程隊列
    sendq    waitq          // 等待的寫元素的協(xié)程隊列
    ... 
}

其中,有一個屬性是我們應該關(guān)注的,那就是closed,這玩意標識了管道是否關(guān)閉,這玩意為1代表關(guān)閉了,為0代表是開啟的.

詳細分析

好的,接下來我們繼續(xù)本文探討的問題在Go語言中,我們是否可以使用管道的第二個返回值來判斷管道是否關(guān)閉?先給出結(jié)論 : 從嚴格意義上來講是不可以的,其實表示是否成功讀取數(shù)據(jù),但是在緩存區(qū)為0的時候,ok的狀態(tài)和管道狀態(tài)是一致的,所以會被誤認為,這個ok是代表管道的狀態(tài)可以看下面的例子

package main
import (
   "fmt"
   "time"
)
func main() {
   a2 := make(chan int, 2)
   go demo(a2)
   value2, ok2 := <-a2
   fmt.Printf("value2:%v,ok2:%v\n", value2, ok2)
   time.Sleep(3 * time.Second)
   value3, ok3 := <-a2
   fmt.Printf("value3:%v,ok3:%v\n", value3, ok3)
}
func demo(a chan int) {
   defer func() {
      close(a)
      fmt.Println("管道已經(jīng)關(guān)閉")
   }()
   a <- 1
   a <- 2
}

解釋一下運行流程

1.首先創(chuàng)建了一個緩存區(qū)為2的管道a2

2.然后用go關(guān)鍵字

將demo函數(shù)開辟出一個新的協(xié)程運行,此時demo和main是同一級的關(guān)系,同時運行,此時main函數(shù)會繼續(xù)向下執(zhí)行,發(fā)現(xiàn)是從管道中讀取一個元素,然后就會等待demo函數(shù)會向管道中傳入值,demo函數(shù)的運行過程是這樣的,它發(fā)現(xiàn)管道a2的緩存是2,所以剛好把元素存入,然后就執(zhí)行關(guān)閉管道,然后demo協(xié)程銷毀

3.main函數(shù)繼續(xù)執(zhí)行,接收到a2管道的一個元素之后,然后返回value2和ok2,然后進行打印

4.然后休眠3秒鐘

5.然后繼續(xù)讀取a2管道的元素,得到value3和ok3,然后打印

ok2和ok3都為true

’ 管道已經(jīng)關(guān)閉 ’ 這是最先打印的,無論運行多少次,都是一樣的,而且我還特地將main函數(shù)暫停了3秒,所以我可以保證demo函數(shù)已經(jīng)執(zhí)行完畢,demo協(xié)程已經(jīng)銷毀,然后再執(zhí)行的第二個管道的數(shù)據(jù)的讀取

逐步調(diào)試

那我們調(diào)試一下,可以發(fā)現(xiàn),執(zhí)行了make函數(shù)創(chuàng)建管道之后,管道沒有關(guān)閉,我前面特意提了管道的數(shù)據(jù)結(jié)構(gòu),其中closed是標識管道是否關(guān)閉的

繼續(xù)調(diào)試,我們可以發(fā)現(xiàn),在讀取完管道a2的第一個值賦值給value2和ok2的時候,此時通道已經(jīng)關(guān)閉

value2的值為1,ok2為true

繼續(xù)調(diào)試,通道還是關(guān)閉狀態(tài),但是ok3的值還是true,看下面的第二張圖

所以讀取管道元素傳來的第二個值,并不是代表管道是否關(guān)閉!

那它代表什么?

其實是代表讀取數(shù)據(jù)是否成功,或者說代表緩存區(qū)是否還有數(shù)據(jù)

首先我們要知道, 關(guān)閉了的管道, 我們還是可以進行讀取的, 這個設(shè)定是因為有緩存的存在, 但是如果管道關(guān)閉了的話,又沒有值,讀取的話,會是類型的默認值和false,也就是讀取未成功

當然如果是緩存區(qū)為0的情況,ok的值和管道的狀態(tài)是一致的

var c = make(chan int)
close(c)
value, ok := <-c
fmt.Printf("value:%v \nok:%v \n", value, ok)

運行結(jié)果:

以上就是詳解go語言判斷管道是否關(guān)閉的常見誤區(qū)的詳細內(nèi)容,更多關(guān)于go判斷管道是否關(guān)閉的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Golang使用sqlite3數(shù)據(jù)庫實現(xiàn)CURD操作

    Golang使用sqlite3數(shù)據(jù)庫實現(xiàn)CURD操作

    這篇文章主要為大家詳細介紹了Golang使用sqlite3數(shù)據(jù)庫實現(xiàn)CURD操作的相關(guān)知識,文中的示例代碼簡潔易懂,有需要的小伙伴可以參考一下
    2025-03-03
  • Golang中堆排序的實現(xiàn)

    Golang中堆排序的實現(xiàn)

    堆是一棵基于數(shù)組實現(xiàn)的特殊的完全二叉樹,本文主要介紹了Golang中堆排序的實現(xiàn),文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • Golang學習筆記之安裝Go1.15版本(win/linux/macos/docker安裝)

    Golang學習筆記之安裝Go1.15版本(win/linux/macos/docker安裝)

    這篇文章主要介紹了Golang學習筆記之安裝Go1.15版本(win/linux/macos/docker安裝),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-12-12
  • 輕松構(gòu)建Go應用的Dockerfile

    輕松構(gòu)建Go應用的Dockerfile

    本文介紹了如何制作一個用于構(gòu)建和運行Go應用程序的Docker鏡像的Dockerfile的相關(guān)資料,需要的朋友可以參考下
    2023-10-10
  • 實現(xiàn)像php一樣方便的go ORM數(shù)據(jù)庫操作示例詳解

    實現(xiàn)像php一樣方便的go ORM數(shù)據(jù)庫操作示例詳解

    這篇文章主要為大家介紹了實現(xiàn)像php一樣方便的go ORM數(shù)據(jù)庫操作示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-12-12
  • Golang最大遞減數(shù)算法問題分析

    Golang最大遞減數(shù)算法問題分析

    這篇文章主要介紹了Golang最大遞減數(shù)算法問題分析,結(jié)合實例形式分析了Go語言數(shù)字遍歷與運算相關(guān)操作技巧,需要的朋友可以參考下
    2017-01-01
  • Golang Recover處理錯誤原理解析

    Golang Recover處理錯誤原理解析

    Golang 中的?recover?是一個鮮為人知但非常有趣和強大的功能,讓我們看看它是如何工作的,以及在 Outreach.io 中如何利用它來處理 Kubernetes 中的錯誤
    2023-12-12
  • Go語言實現(xiàn)文件上傳

    Go語言實現(xiàn)文件上傳

    這篇文章主要為大家詳細介紹了Go語言實現(xiàn)文件上傳,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • 使用Go語言開發(fā)短鏈接服務的方法

    使用Go語言開發(fā)短鏈接服務的方法

    短鏈接一般是通過映射關(guān)系,將長長的一串網(wǎng)址,映射到幾個字符的短鏈接上,建立好這種映射關(guān)系之后保存到數(shù)據(jù)庫里,用戶每次訪問短鏈接的時候,這篇文章主要介紹了使用Go語言開發(fā)一個短鏈接服務,需要的朋友可以參考下
    2024-03-03
  • Golang如何自定義logrus日志保存為日志文件

    Golang如何自定義logrus日志保存為日志文件

    這篇文章主要給大家介紹了關(guān)于Golang如何自定義logrus日志保存為日志文件的相關(guān)資料,logrus是目前Github上star數(shù)量最多的日志庫,logrus功能強大,性能高效,而且具有高度靈活性,提供了自定義插件的功能,很多開源項目都是用了logrus來記錄其日志,需要的朋友可以參考下
    2024-02-02

最新評論