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

Golang pipe在不同場景下遠程交互

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

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

Pipe介紹

pipe實現(xiàn)從一個進程重定向至另一個進程,它是雙向數(shù)據(jù)通道,用于實現(xià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簡單示例

在實現(xià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寫數(shù)據(jù),然后使用io.Copy函數(shù)從管道Reader中拷貝數(shù)據(jù)至標(biāo)準(zhǔn)輸出:

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

在協(xié)程中寫數(shù)據(jù)是因為每次寫PipeWriter都阻塞直到PipeReader完全消費了數(shù)據(jù)。

運行程序:

go run main.go 
Hello there

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

Go cmd StdoutPipe

當(dāng)命令啟動時,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))
    }
}

上面代碼啟動ping命令,然后從其輸出中讀取4行. 這行代碼啟動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行并輸出到控制臺,運行程序,輸出結(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

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

http請求處理中使用管道

下面示例展示在http請求處理中使用管道。運行date命令,通過HTTP輸出結(jié)果,可以實現(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)錯誤。

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.最后運行程序查看結(jié)果:

$ go run handler.go 
server started on port 8080

使用curl或瀏覽器訪問地址:localhost:8080,可以看到:

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

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

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

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

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))
}

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

首先定義管道,然后在協(xié)程中給管道Writer寫入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ù)傳入請求:

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))

運行程序輸出結(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"
  }, 
  // 省略...
}

通過管道讀標(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ū)。然后計算塊數(shù)和字節(jié)數(shù),最后答應(yīng)緩沖區(qū)內(nèi)容。

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

Bytes: 43 Chunks: 1

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

Go Stat

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

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)
    }
}

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

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

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

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

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

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

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

總結(jié)

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

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

相關(guān)文章

  • golang中字符串MD5生成方式總結(jié)

    golang中字符串MD5生成方式總結(jié)

    在本篇文章里小編給大家整理的是一篇關(guān)于golang中字符串MD5生成方式總結(jié)內(nèi)容,有興趣的朋友們可以跟著學(xué)習(xí)參考下。
    2021-07-07
  • Go 語言中的空接口(推薦)

    Go 語言中的空接口(推薦)

    這篇文章主要介紹了Go 語言中的空接口的實現(xiàn)方法,本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • Golang字符串的拼接方法匯總

    Golang字符串的拼接方法匯總

    字符串拼接在日常開發(fā)中是很常見的需求,今天我們來探討下如何用golang來實現(xiàn)字符串的拼接
    2018-10-10
  • GoLang sync.Pool簡介與用法

    GoLang sync.Pool簡介與用法

    這篇文章主要介紹了GoLang sync.Pool簡介與用法,Pool是可伸縮、并發(fā)安全的臨時對象池,用來存放已經(jīng)分配但暫時不用的臨時對象,通過對象重用機制,緩解GC壓力,提高程序性能
    2023-01-01
  • 利用dep代替go get獲取私有庫的方法教程

    利用dep代替go get獲取私有庫的方法教程

    go get 從指定源上面下載或者更新指定的代碼和依賴,并對他們進行編譯和安裝,但go get功能比較差,所以下面這篇文章主要給大家介紹了關(guān)于利用dep代替go get獲取私有庫的相關(guān)資料,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-11-11
  • Go基礎(chǔ)教程系列之Go接口使用詳解

    Go基礎(chǔ)教程系列之Go接口使用詳解

    這篇文章主要介紹了Go基礎(chǔ)教程系列之Go接口使用詳解,需要的朋友可以參考下
    2022-04-04
  • Go語言開發(fā)瀏覽器視頻流rtsp轉(zhuǎn)webrtc播放

    Go語言開發(fā)瀏覽器視頻流rtsp轉(zhuǎn)webrtc播放

    這篇文章主要為大家介紹了Go語言開發(fā)瀏覽器視頻流rtsp轉(zhuǎn)webrtc播放的過程示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-04-04
  • 詳解golang中make與new的異同點和用法

    詳解golang中make與new的異同點和用法

    這篇文章將給大家介紹了go語言中函數(shù)new與make的使用和區(qū)別,關(guān)于go語言中new和make是內(nèi)建的兩個函數(shù),主要用來創(chuàng)建分配類型內(nèi)存,文中通過代碼示例介紹的非常詳細,具有一定的參考價值,需要的朋友可以參考下
    2024-01-01
  • Golang+Vue輕松構(gòu)建Web應(yīng)用的方法步驟

    Golang+Vue輕松構(gòu)建Web應(yīng)用的方法步驟

    本文主要介紹了Golang+Vue輕松構(gòu)建Web應(yīng)用,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-05-05
  • 使用Go語言開發(fā)自動化API測試工具詳解

    使用Go語言開發(fā)自動化API測試工具詳解

    這篇文章主要為大家詳細介紹了如何使用Go語言開發(fā)自動化API測試工具,文中的示例代碼講解詳細,具有一定的借鑒價值,有需要的小伙伴可以參考下
    2024-03-03

最新評論