欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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

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

前言

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

樣例

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

package main
import "fmt"
func main() {
    // 創(chuàng)建一個(gè)整型管道
    ch := make(chan int)
    // 啟動(dòng)一個(gè)協(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)

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

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

其中,有一個(gè)屬性是我們應(yīng)該關(guān)注的,那就是closed,這玩意標(biāo)識(shí)了管道是否關(guān)閉,這玩意為1代表關(guān)閉了,為0代表是開(kāi)啟的.

詳細(xì)分析

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

解釋一下運(yùn)行流程

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

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

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

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

4.然后休眠3秒鐘

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

ok2和ok3都為true

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

逐步調(diào)試

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

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

value2的值為1,ok2為true

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

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

那它代表什么?

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

首先我們要知道, 關(guān)閉了的管道, 我們還是可以進(jìn)行讀取的, 這個(gè)設(shè)定是因?yàn)橛芯彺娴拇嬖? 但是如果管道關(guān)閉了的話,又沒(méi)有值,讀取的話,會(huì)是類(lèi)型的默認(rèn)值和false,也就是讀取未成功

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

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

運(yùn)行結(jié)果:

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

相關(guān)文章

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

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

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

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

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

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

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

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

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

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

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

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

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

    Golang Recover處理錯(cuò)誤原理解析

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

    Go語(yǔ)言實(shí)現(xiàn)文件上傳

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

    使用Go語(yǔ)言開(kāi)發(fā)短鏈接服務(wù)的方法

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

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

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

最新評(píng)論