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

使用Go?goroutine實(shí)現(xiàn)并發(fā)的Clock服務(wù)

 更新時(shí)間:2023年06月29日 15:12:05   作者:架構(gòu)精進(jìn)之路  
這篇文章主要為大家詳細(xì)介紹了如何使用Go?goroutine實(shí)現(xiàn)并發(fā)的Clock服務(wù),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

網(wǎng)絡(luò)編程是并發(fā)大顯身手的一個(gè)領(lǐng)域,由于服務(wù)器是最典型的需要同時(shí)處理很多連接的程序,這些連接一般來(lái)自于彼此獨(dú)立的客戶端。

本文我們會(huì)用到go語(yǔ)言的net包,這個(gè)包提供編寫一個(gè)網(wǎng)絡(luò)客戶端或者服務(wù)器程序的基本組件,無(wú)論兩者間通信是使用TCP、UDP或者Unix domain sockets。

我們的第一個(gè)例子是一個(gè)順序執(zhí)行的時(shí)鐘服務(wù)器,它會(huì)每隔一秒鐘將當(dāng)前時(shí)間寫到客戶端:

// Clock1 is a TCP server that periodically writes the time.
package main
import (
    "io"
    "log"
    "net"
    "time"
)
func main() {
    listener, err := net.Listen("tcp", "localhost:8000")
    if err != nil {
        log.Fatal(err)
    }
    for {
        conn, err := listener.Accept()
        if err != nil {
            log.Print(err) // e.g., connection aborted
            continue
        }
        handleConn(conn) // handle one connection at a time
    }
}
func handleConn(c net.Conn) {
    defer c.Close()
    for {
        _, err := io.WriteString(c, time.Now().Format("15:04:05\n"))
        if err != nil {
            return // e.g., client disconnected
        }
        time.Sleep(1 * time.Second)
    }
}

Listen函數(shù)創(chuàng)建了一個(gè)net.Listener的對(duì)象,這個(gè)對(duì)象會(huì)監(jiān)聽(tīng)一個(gè)網(wǎng)絡(luò)端口上到來(lái)的連接,在這個(gè)例子里我們用的是TCP的localhost:8000端口。listener對(duì)象的Accept方法會(huì)直接阻塞,直到一個(gè)新的連接被創(chuàng)建,然后會(huì)返回一個(gè)net.Conn對(duì)象來(lái)表示這個(gè)連接。

handleConn函數(shù)會(huì)處理一個(gè)完整的客戶端連接。在一個(gè)for死循環(huán)中,用time.Now()獲取當(dāng)前時(shí)刻,然后寫到客戶端。由于net.Conn實(shí)現(xiàn)了io.Writer接口,我們可以直接向其寫入內(nèi)容。這個(gè)死循環(huán)會(huì)一直執(zhí)行,直到寫入失敗。最可能的原因是客戶端主動(dòng)斷開(kāi)連接。這種情況下handleConn函數(shù)會(huì)用defer調(diào)用關(guān)閉服務(wù)器側(cè)的連接,然后返回到主函數(shù),繼續(xù)等待下一個(gè)連接請(qǐng)求。

time.Time.Format方法提供了一種格式化日期和時(shí)間信息的方式。它的參數(shù)是一個(gè)格式化模板,標(biāo)識(shí)如何來(lái)格式化時(shí)間,而這個(gè)格式化模板限定為Mon Jan 2 03:04:05PM 2006 UTC-0700。有8個(gè)部分(周幾、月份、一個(gè)月的第幾天……)??梢砸匀我獾男问絹?lái)組合前面這個(gè)模板;出現(xiàn)在模板中的部分會(huì)作為參考來(lái)對(duì)時(shí)間格式進(jìn)行輸出。

在上面的例子中我們只用到了小時(shí)、分鐘和秒。time包里定義了很多標(biāo)準(zhǔn)時(shí)間格式,比如time.RFC1123。在進(jìn)行格式化的逆向操作time.Parse時(shí),也會(huì)用到同樣的策略。(譯注:這是go語(yǔ)言和其它語(yǔ)言相比比較奇葩的一個(gè)地方。你需要記住格式化字符串是1月2日下午3點(diǎn)4分5秒零六年UTC-0700,而不像其它語(yǔ)言那樣Y-m-d H:i:s一樣,當(dāng)然了這里可以用1234567的方式來(lái)記憶,倒是也不麻煩。)

為了連接例子里的服務(wù)器,我們需要一個(gè)客戶端程序,比如netcat這個(gè)工具(nc命令),這個(gè)工具可以用來(lái)執(zhí)行網(wǎng)絡(luò)連接操作。

$ go build gopl.io/ch8/clock1
$ ./clock1 &
$ nc localhost 8000
13:58:54
13:58:55
13:58:56
13:58:57
^C

客戶端將服務(wù)器發(fā)來(lái)的時(shí)間顯示了出來(lái),我們用Control+C來(lái)中斷客戶端的執(zhí)行,在Unix系統(tǒng)上,你會(huì)看到^C這樣的響應(yīng)。如果你的系統(tǒng)沒(méi)有裝nc這個(gè)工具,你可以用telnet來(lái)實(shí)現(xiàn)同樣的效果,或者也可以用我們下面的這個(gè)用go寫的簡(jiǎn)單的telnet程序,用net.Dial就可以簡(jiǎn)單地創(chuàng)建一個(gè)TCP連接:

// Netcat1 is a read-only TCP client.
package main
import (
    "io"
    "log"
    "net"
    "os"
)
func main() {
    conn, err := net.Dial("tcp", "localhost:8000")
    if err != nil {
        log.Fatal(err)
    }
    defer conn.Close()
    mustCopy(os.Stdout, conn)
}
func mustCopy(dst io.Writer, src io.Reader) {
    if _, err := io.Copy(dst, src); err != nil {
        log.Fatal(err)
    }
}

這個(gè)程序會(huì)從連接中讀取數(shù)據(jù),并將讀到的內(nèi)容寫到標(biāo)準(zhǔn)輸出中,直到遇到end of file的條件或者發(fā)生錯(cuò)誤。mustCopy這個(gè)函數(shù)我們?cè)诒竟?jié)的幾個(gè)例子中都會(huì)用到。讓我們同時(shí)運(yùn)行兩個(gè)客戶端來(lái)進(jìn)行一個(gè)測(cè)試,這里可以開(kāi)兩個(gè)終端窗口,下面左邊的是其中的一個(gè)的輸出,右邊的是另一個(gè)的輸出:

$ go build gopl.io/ch8/netcat1
$ ./netcat1
13:58:54                               $ ./netcat1
13:58:55
13:58:56
^C
                                       13:58:57
                                       13:58:58
                                       13:58:59
                                       ^C
$ killall clock1

killall命令是一個(gè)Unix命令行工具,可以用給定的進(jìn)程名來(lái)殺掉所有名字匹配的進(jìn)程。

第二個(gè)客戶端必須等待第一個(gè)客戶端完成工作,這樣服務(wù)端才能繼續(xù)向后執(zhí)行;因?yàn)槲覀冞@里的服務(wù)器程序同一時(shí)間只能處理一個(gè)客戶端連接。我們這里對(duì)服務(wù)端程序做一點(diǎn)小改動(dòng),使其支持并發(fā):在handleConn函數(shù)調(diào)用的地方增加go關(guān)鍵字,讓每一次handleConn的調(diào)用都進(jìn)入一個(gè)獨(dú)立的goroutine。

for {
    conn, err := listener.Accept()
    if err != nil {
        log.Print(err) // e.g., connection aborted
        continue
    }
    go handleConn(conn) // handle connections concurrently
}

現(xiàn)在多個(gè)客戶端可以同時(shí)接收到時(shí)間了:

$ go build gopl.io/ch8/clock2
$ ./clock2 &
$ go build gopl.io/ch8/netcat1
$ ./netcat1
14:02:54                               $ ./netcat1
14:02:55                               14:02:55
14:02:56                               14:02:56
14:02:57                               ^C
14:02:58
14:02:59                               $ ./netcat1
14:03:00                               14:03:00
14:03:01                               14:03:01
^C                                     14:03:02
                                       ^C
$ killall clock2

至此,完成!

到此這篇關(guān)于使用Go goroutine實(shí)現(xiàn)并發(fā)的Clock服務(wù)的文章就介紹到這了,更多相關(guān)Go goroutine內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Go語(yǔ)言實(shí)現(xiàn)定時(shí)器的方法

    Go語(yǔ)言實(shí)現(xiàn)定時(shí)器的方法

    這篇文章主要介紹了Go語(yǔ)言實(shí)現(xiàn)定時(shí)器的方法,涉及Go語(yǔ)言時(shí)間操作技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下
    2015-02-02
  • go語(yǔ)言通過(guò)結(jié)構(gòu)體生成json示例解析

    go語(yǔ)言通過(guò)結(jié)構(gòu)體生成json示例解析

    這篇文章主要為大家介紹了go語(yǔ)言通過(guò)結(jié)構(gòu)體生成json示例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-04-04
  • Golang?內(nèi)存模型The?Go?Memory?Model

    Golang?內(nèi)存模型The?Go?Memory?Model

    這篇文章主要為大家介紹了Golang?內(nèi)存模型The?Go?Memory?Model實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-11-11
  • Golang并發(fā)利器sync.Once的用法詳解

    Golang并發(fā)利器sync.Once的用法詳解

    在某些場(chǎng)景下,我們需要初始化一些資源。有時(shí)會(huì)采用延遲初始化的方式,在真正需要資源的時(shí)候才進(jìn)行初始化。在這種情況下,Go語(yǔ)言中的sync.Once提供一個(gè)優(yōu)雅且并發(fā)安全的解決方案,本文將對(duì)其進(jìn)行詳細(xì)介紹
    2023-04-04
  • Go利用GJSON組件解鎖JSON讀取新姿勢(shì)

    Go利用GJSON組件解鎖JSON讀取新姿勢(shì)

    Go 標(biāo)準(zhǔn)庫(kù)提供了 encoding/json 包用于處理 json 數(shù)據(jù),同時(shí)第三方庫(kù) GJSON & SJSON 也在 json 處理方面表現(xiàn)出色,下面我們就來(lái)看看如何使用GJSON解鎖JSON讀取新方法吧
    2025-03-03
  • 深入探索Go語(yǔ)言中的高效數(shù)據(jù)結(jié)構(gòu)堆

    深入探索Go語(yǔ)言中的高效數(shù)據(jù)結(jié)構(gòu)堆

    堆,作為一種基本的數(shù)據(jù)結(jié)構(gòu),以其在優(yōu)先隊(duì)列和排序算法中提供高效解決方案的能力而聞名。在本文中,我們將深入探討堆的內(nèi)部工作原理,包括其特性、實(shí)現(xiàn)細(xì)節(jié)以及在現(xiàn)代編程中的應(yīng)用
    2008-06-06
  • Go語(yǔ)言中更優(yōu)雅的錯(cuò)誤處理

    Go語(yǔ)言中更優(yōu)雅的錯(cuò)誤處理

    Go語(yǔ)言中的錯(cuò)誤處理是一個(gè)被大家經(jīng)常拿出來(lái)討論的話題(另外一個(gè)是泛型)。篇文章我們將討論一下如何在現(xiàn)行的 Golang 框架下提供更友好和優(yōu)雅的錯(cuò)誤處理。需要的朋友們可以參考借鑒,下面來(lái)一起看看吧。
    2017-02-02
  • golang讀取文件的常用方法總結(jié)

    golang讀取文件的常用方法總結(jié)

    今天小編就為大家分享一篇關(guān)于golang讀取文件的常用方法總結(jié),小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧
    2019-04-04
  • golang簡(jiǎn)易令牌桶算法實(shí)現(xiàn)代碼

    golang簡(jiǎn)易令牌桶算法實(shí)現(xiàn)代碼

    這篇文章主要介紹了golang簡(jiǎn)易令牌桶算法實(shí)現(xiàn)代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • Golang設(shè)計(jì)模式之適配器模式詳細(xì)講解

    Golang設(shè)計(jì)模式之適配器模式詳細(xì)講解

    這篇文章主要介紹了使用go實(shí)現(xiàn)適配器模式,這個(gè)模式就是用來(lái)做適配的,它將不兼容的接口轉(zhuǎn)換為可兼容的接口,讓原本由于接口不兼容而不能一起工作的類可以一起工作,需要的朋友可以參考下
    2023-01-01

最新評(píng)論