最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Golang pipe在不同場(chǎng)景下遠(yuǎn)程交互

 更新時(shí)間:2023年03月08日 09:16:33   作者:夢(mèng)想畫(huà)家  
這篇文章主要介紹了Golang pipe在不同場(chǎng)景下遠(yuǎn)程交互,pipe實(shí)現(xiàn)從一個(gè)進(jìn)程重定向至另一個(gè)進(jìn)程,它是雙向數(shù)據(jù)通道,用于實(shí)現(xiàn)進(jìn)行間通信

本文介紹Golang pipe,以及在不同場(chǎng)景下的應(yīng)用。

Pipe介紹

pipe實(shí)現(xiàn)從一個(gè)進(jìn)程重定向至另一個(gè)進(jìn)程,它是雙向數(shù)據(jù)通道,用于實(shí)現(xiàn)進(jìn)行間通信。

io.Pipe函數(shù)創(chuàng)建內(nèi)存同步通道,用于連接io.Reader和io.Writer. 本文示例使用環(huán)境為:

go version
go version go1.19.3 linux/amd64

Go pipe簡(jiǎn)單示例

在實(shí)現(xiàn)遠(yuǎn)程交互之前,先看下面簡(jiǎn)單示例,演示如何使用io.Pipe函數(shù):

package main
import (
    "fmt"
    "io"
    "log"
    "os"
)
func main() {
    r, w := io.Pipe()
    go func() {
        fmt.Fprint(w, "Hello there\n")
        w.Close()
    }()
    _, err := io.Copy(os.Stdout, r)
    if err != nil {
        log.Fatal(err)
    }
}

首先創(chuàng)建pipe,然后在協(xié)程中給管道的writer寫(xiě)數(shù)據(jù),然后使用io.Copy函數(shù)從管道Reader中拷貝數(shù)據(jù)至標(biāo)準(zhǔn)輸出:

go func() {
    fmt.Fprint(w, "Hello there\n")
    w.Close()
}()

在協(xié)程中寫(xiě)數(shù)據(jù)是因?yàn)槊看螌?xiě)PipeWriter都阻塞直到PipeReader完全消費(fèi)了數(shù)據(jù)。

運(yùn)行程序:

go run main.go 
Hello there

通過(guò)這個(gè)簡(jiǎn)單示例,展示了管道重定向能力,了解這個(gè)基本原理后,下面先看Shell命令的管道,最終我們的目標(biāo)是通過(guò)WEB方式實(shí)現(xiàn)遠(yuǎn)程命令行交互。

Go cmd StdoutPipe

當(dāng)命令啟動(dòng)時(shí),Cmd的StdoutPipe返回管道連接命令的標(biāo)準(zhǔn)輸出:

package main
import (
    "bufio"
    "fmt"
    "log"
    "os"
    "os/exec"
)
func main() {
    cmd := exec.Command("ping", "www.baidu.com")
    stdout, err := cmd.StdoutPipe()
    if err != nil {
        log.Fatal(err)
    }
    cmd.Start()
    buf := bufio.NewReader(stdout) 
    num := 0
    for {
        line, _, _ := buf.ReadLine()
        if num > 3 {
            os.Exit(0)
        }
        num += 1
        fmt.Println(string(line))
    }
}

上面代碼啟動(dòng)ping命令,然后從其輸出中讀取4行. 這行代碼啟動(dòng)ping命令:

    cmd := exec.Command("ping", "www.baidu.com")
    stdout, err := cmd.StdoutPipe()
    buf := bufio.NewReader(stdout) 

接著獲取命令的標(biāo)準(zhǔn)輸出,并保存輸出之buf中。下面從緩沖中讀取4行:

for {
    line, _, _ := buf.ReadLine()
    if num > 3 {
        os.Exit(0)
    }
    num += 1
    fmt.Println(string(line))
}

讀取4行并輸出到控制臺(tái),運(yùn)行程序,輸出結(jié)果如下:

go run main.go
PING www.a.shifen.com (180.101.50.188) 56(84) bytes of data.
64 bytes from 180.101.50.188 (180.101.50.188): icmp_seq=1 ttl=53 time=12.0 ms
64 bytes from 180.101.50.188 (180.101.50.188): icmp_seq=2 ttl=53 time=11.2 ms
64 bytes from 180.101.50.188 (180.101.50.188): icmp_seq=3 ttl=53 time=10.5 ms

通過(guò)這個(gè)示例,成功地把命令的執(zhí)行結(jié)果捕獲到buffer中,并能夠增加處理邏輯再輸出到控制臺(tái)。

http請(qǐng)求處理中使用管道

下面示例展示在http請(qǐng)求處理中使用管道。運(yùn)行date命令,通過(guò)HTTP輸出結(jié)果,可以實(shí)現(xiàn)元從查看命令執(zhí)行結(jié)果。

package main
import (
    "fmt"
    "io"
    "net/http"
    "os/exec"
)
func handler(w http.ResponseWriter, r *http.Request) {
    cmd := exec.Command("date")
    pr, pw := io.Pipe()
    defer pw.Close()
    cmd.Stdout = pw
    cmd.Stderr = pw
    go io.Copy(w, pr)
    cmd.Run()
}
func main() {
    http.HandleFunc("/", handler)
    fmt.Println("server started on port 8080")
    http.ListenAndServe(":8080", nil)
}

關(guān)鍵代碼為創(chuàng)建管道,并把PipeWriter賦給命令的標(biāo)準(zhǔn)輸出和標(biāo)準(zhǔn)錯(cuò)誤。

cmd := exec.Command("date")
pr, pw := io.Pipe()
defer pw.Close()
cmd.Stdout = pw
cmd.Stderr = pw

go io.Copy(w, pr)

然后在協(xié)程中拷貝PipeReader至http.ResponseWriter.最后運(yùn)行程序查看結(jié)果:

$ go run handler.go 
server started on port 8080

使用curl或?yàn)g覽器訪問(wèn)地址:localhost:8080,可以看到:

2023年 02月 22日 星期三 17:06:11 CST

修改上面程序,把命令作為參數(shù),即可實(shí)現(xiàn)遠(yuǎn)程交互。下面我們看看如何利用管道給輸入端寫(xiě)入數(shù)據(jù),包括http請(qǐng)求和命令的標(biāo)準(zhǔn)輸入。

利用管道提交post請(qǐng)求json數(shù)據(jù)

下面示例給https://httpbin.org/post請(qǐng)求地址提交json數(shù)據(jù)作為請(qǐng)求體。

package main
import (
    "encoding/json"
    "fmt"
    "io"
    "io/ioutil"
    "log"
    "net/http"
)
type PayLoad struct {
    Content string
}
func main() {
    r, w := io.Pipe()
    go func() {
        defer w.Close()
        err := json.NewEncoder(w).Encode(&PayLoad{Content: "Hello there!"})
        if err != nil {
            log.Fatal(err)
        }
    }()
    resp, err := http.Post("https://httpbin.org/post", "application/json", r)
    if err != nil {
        log.Fatal(err)
    }
    body, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    fmt.Println(string(body))
}

上面示例實(shí)現(xiàn)給post請(qǐng)求提交json數(shù)據(jù),并讀取響應(yīng)內(nèi)容。

首先定義管道,然后在協(xié)程中給管道Writer寫(xiě)入json數(shù)據(jù):

go func() {
    defer w.Close()
    err := json.NewEncoder(w).Encode(&PayLoad{Content: "Hello there!"})
    if err != nil {
        log.Fatal(err)
    }
}()

然后把管道Reader作為參數(shù)傳入請(qǐng)求:

resp, err := http.Post("https://httpbin.org/post", "application/json", r)

最后讀取響應(yīng)內(nèi)容:

body, err := ioutil.ReadAll(resp.Body)
if err != nil {
    log.Fatal(err)
}
fmt.Println(string(body))

運(yùn)行程序輸出結(jié)果:

go run main.go
{
  "args": {}, 
  "data": "{\"Content\":\"Hello there!\"}\n", 
  "files": {}, 
  "form": {}, 
  "headers": {
    "Accept-Encoding": "gzip", 
    "Content-Type": "application/json", 
    "Host": "httpbin.org", 
    "Transfer-Encoding": "chunked", 
    "User-Agent": "Go-http-client/2.0", 
    "X-Amzn-Trace-Id": "Root=1-63f5c8c6-4a14ee9a2dc14e352f234fae"
  }, 
  // 省略...
}

通過(guò)管道讀標(biāo)準(zhǔn)輸入

下面示例利用管道從標(biāo)準(zhǔn)輸入讀取數(shù)據(jù),并打印數(shù)據(jù)及數(shù)據(jù)字節(jié)數(shù)、塊數(shù):

package main
import (
    "bufio"
    "fmt"
    "io"
    "log"
    "os"
)
func main() {
    nBytes, nChunks := int64(0), int64(0)
    r := bufio.NewReader(os.Stdin)
    buf := make([]byte, 0, 4*1024)
    for {
        n, err := r.Read(buf[:cap(buf)])
        buf = buf[:n]
        if n == 0 {
            if err == nil {
                continue
            }
            if err == io.EOF {
                break
            }
            log.Fatal(err)
        }
        nChunks++
        nBytes += int64(len(buf))
        fmt.Println(string(buf))
        if err != nil && err != io.EOF {
            log.Fatal(err)
        }
    }
    fmt.Println("Bytes:", nBytes, "Chunks:", nChunks)
}

首先定義包裝標(biāo)準(zhǔn)輸入Reader:

r := bufio.NewReader(os.Stdin)
buf := make([]byte, 0, 4*1024)
n, err := r.Read(buf[:cap(buf)])
buf = buf[:n]
nChunks++
nBytes += int64(len(buf))
fmt.Println(string(buf))

然后創(chuàng)建4kb緩沖區(qū),從標(biāo)準(zhǔn)輸入讀數(shù)據(jù)至緩沖區(qū)。然后計(jì)算塊數(shù)和字節(jié)數(shù),最后答應(yīng)緩沖區(qū)內(nèi)容。

date | go run main.go
2023年 02月 22日 星期三 16:08:17 CST

Bytes: 43 Chunks: 1

這里通過(guò)|操作傳遞date命令的輸出結(jié)果,顯示內(nèi)容與預(yù)期一致。

Go Stat

Stat函數(shù)返回FileInfo結(jié)構(gòu)體,描述文件信息。我們可以利用其檢查數(shù)據(jù)是否來(lái)自終端。

package main
import (
    "bufio"
    "fmt"
    "log"
    "os"
)
func main() {
    stat, _ := os.Stdin.Stat()
    if (stat.Mode() & os.ModeCharDevice) == 0 {
        var buf []byte
        scanner := bufio.NewScanner(os.Stdin)
        for scanner.Scan() {
            buf = append(buf, scanner.Bytes()...)
        }
        if err := scanner.Err(); err != nil {
            log.Fatal(err)
        }
        fmt.Printf("Hello %s!\n", buf)
    } else {
        fmt.Print("Enter your name: ")
        var name string
        fmt.Scanf("%s", &name)
        fmt.Printf("Hello %s!\n", name)
    }
}

這個(gè)示例數(shù)據(jù)可能來(lái)自終端或管道。為了判斷,通過(guò)下面代碼獲取stat:

stat, _ := os.Stdin.Stat()

獲取到標(biāo)準(zhǔn)輸入的FileInfo結(jié)構(gòu)體后進(jìn)行判斷:

if (stat.Mode() & os.ModeCharDevice) == 0 {

這行判斷數(shù)據(jù)來(lái)自管道,反之則為終端。即如果沒(méi)有管道提供數(shù)據(jù),則提示用戶輸入數(shù)據(jù)。運(yùn)行程序:

$ echo "golang" | go run main.go
Hello golang!

$go run main.go
Enter your name: java
Hello java!

總結(jié)

本文介紹了Golang管道的使用,除了實(shí)現(xiàn)遠(yuǎn)程命令交互,還介紹了獲取標(biāo)準(zhǔn)輸入內(nèi)容、判斷標(biāo)準(zhǔn)輸入數(shù)據(jù)來(lái)源。讀者組合這些簡(jiǎn)單示例,一定能夠編寫(xiě)出炫酷的應(yīng)用。

到此這篇關(guān)于Golang pipe在不同場(chǎng)景下遠(yuǎn)程交互的文章就介紹到這了,更多相關(guān)Golang pipe遠(yuǎn)程交互內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 十個(gè)Golang開(kāi)發(fā)中應(yīng)該避免的錯(cuò)誤總結(jié)

    十個(gè)Golang開(kāi)發(fā)中應(yīng)該避免的錯(cuò)誤總結(jié)

    Go是一種靜態(tài)類型的、并發(fā)的、垃圾收集的編程語(yǔ)言,由谷歌開(kāi)發(fā)。開(kāi)發(fā)人員在編寫(xiě)Go代碼時(shí)總會(huì)有一些常見(jiàn)的錯(cuò)誤,下面是Go語(yǔ)言中需要避免的十大壞錯(cuò)誤,希望對(duì)大家有所幫助
    2023-03-03
  • Go語(yǔ)言操作etcd的示例詳解

    Go語(yǔ)言操作etcd的示例詳解

    etcd是使用Go語(yǔ)言開(kāi)發(fā)的一個(gè)開(kāi)源的、高可用的分布式key—value存儲(chǔ)系統(tǒng),可以用于配置共享和服務(wù)的注冊(cè)和發(fā)現(xiàn),下面我們就來(lái)看看Go語(yǔ)言是如何操作etcd的吧
    2024-03-03
  • 圖文詳解go語(yǔ)言反射實(shí)現(xiàn)原理

    圖文詳解go語(yǔ)言反射實(shí)現(xiàn)原理

    這篇文章主要介紹了圖文詳解go語(yǔ)言反射實(shí)現(xiàn)原理,本文圖文并茂給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友參考下吧,需要的朋友可以參考下
    2020-02-02
  • 詳解Go如何優(yōu)雅的對(duì)時(shí)間進(jìn)行格式化

    詳解Go如何優(yōu)雅的對(duì)時(shí)間進(jìn)行格式化

    這篇文章主要為大家詳細(xì)介紹了Go語(yǔ)言中是如何優(yōu)雅的對(duì)時(shí)間進(jìn)行格式化的,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下
    2023-06-06
  • Golang操作mongodb的實(shí)現(xiàn)示例

    Golang操作mongodb的實(shí)現(xiàn)示例

    本文主要介紹了Golang操作mongodb的實(shí)現(xiàn)示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2025-03-03
  • Go語(yǔ)言defer語(yǔ)句的三種機(jī)制整理

    Go語(yǔ)言defer語(yǔ)句的三種機(jī)制整理

    在本篇文章里小編給大家分享的是一篇關(guān)于Go語(yǔ)言defer語(yǔ)句的三種機(jī)制整理,需要的朋友們學(xué)習(xí)下吧。
    2020-03-03
  • go-zero接入skywalking實(shí)現(xiàn)鏈路追蹤的詳細(xì)教程

    go-zero接入skywalking實(shí)現(xiàn)鏈路追蹤的詳細(xì)教程

    SkyWalking是一個(gè)開(kāi)源的服務(wù)追蹤系統(tǒng),它專注于分布式系統(tǒng)的可觀測(cè)性和服務(wù)性能分析,它的主要目標(biāo)是幫助開(kāi)發(fā)者理解和優(yōu)化微服務(wù)架構(gòu)中的服務(wù)間交互情況,本文介紹了go-zero接入skywalking鏈路追蹤的詳細(xì)教程,需要的朋友可以參考下
    2024-08-08
  • Go引用github包的詳細(xì)流程步驟

    Go引用github包的詳細(xì)流程步驟

    這篇文章主要給大家介紹了關(guān)于Go引用github包的詳細(xì)流程步驟,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用Go具有一定的參考價(jià)值,需要的朋友可以參考下
    2024-02-02
  • Go實(shí)現(xiàn)自動(dòng)解壓縮包以及讀取docx/doc文件內(nèi)容詳解

    Go實(shí)現(xiàn)自動(dòng)解壓縮包以及讀取docx/doc文件內(nèi)容詳解

    在開(kāi)發(fā)過(guò)程中,我們常常需要處理壓縮包和文檔文件。本文將介紹如何使用Go語(yǔ)言自動(dòng)解壓縮包和讀取docx/doc文件,需要的可以參考一下
    2023-03-03
  • 詳解go語(yǔ)言json的使用技巧

    詳解go語(yǔ)言json的使用技巧

    這篇文章主要介紹了詳解go語(yǔ)言json的使用技巧,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03

最新評(píng)論

盐山县| 浦东新区| 射阳县| 周宁县| 河东区| 惠安县| 乐都县| 鄱阳县| 九台市| 吉林省| 突泉县| 长葛市| 台南市| 温州市| 钟山县| 韩城市| 镇江市| 内丘县| 沛县| 安阳县| 和硕县| 开鲁县| 苍山县| 华宁县| 米林县| 高尔夫| 页游| 锦州市| 青神县| 益阳市| 麦盖提县| 麻栗坡县| 洱源县| 阳原县| 南宁市| 田林县| 荥阳市| 昌邑市| 花垣县| 锡林郭勒盟| 将乐县|