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

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

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

本文介紹Golang pipe,以及在不同場景下的應用。

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ù)至標準輸出:

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

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

運行程序:

go run main.go 
Hello there

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

Go cmd StdoutPipe

當命令啟動時,Cmd的StdoutPipe返回管道連接命令的標準輸出:

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) 

接著獲取命令的標準輸出,并保存輸出之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賦給命令的標準輸出和標準錯誤。

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請求和命令的標準輸入。

利用管道提交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ù),并讀取響應內(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)

最后讀取響應內(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"
  }, 
  // 省略...
}

通過管道讀標準輸入

下面示例利用管道從標準輸入讀取數(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)
}

首先定義包裝標準輸入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ū),從標準輸入讀數(shù)據(jù)至緩沖區(qū)。然后計算塊數(shù)和字節(jié)數(shù),最后答應緩沖區(qū)內(nèi)容。

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

Bytes: 43 Chunks: 1

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

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

獲取到標準輸入的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)遠程命令交互,還介紹了獲取標準輸入內(nèi)容、判斷標準輸入數(shù)據(jù)來源。讀者組合這些簡單示例,一定能夠編寫出炫酷的應用。

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

相關(guān)文章

  • 十個Golang開發(fā)中應該避免的錯誤總結(jié)

    十個Golang開發(fā)中應該避免的錯誤總結(jié)

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

    Go語言操作etcd的示例詳解

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

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

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

    詳解Go如何優(yōu)雅的對時間進行格式化

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

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

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

    Go語言defer語句的三種機制整理

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

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

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

    Go引用github包的詳細流程步驟

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

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

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

    詳解go語言json的使用技巧

    這篇文章主要介紹了詳解go語言json的使用技巧,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2021-03-03

最新評論

苏尼特左旗| 崇信县| 静安区| 道孚县| 兴和县| 安福县| 蒙山县| 长沙市| 冕宁县| 文山县| 行唐县| 明光市| 乐平市| 钟祥市| 泰安市| 祁东县| 静安区| 怀柔区| 邢台县| 突泉县| 张掖市| 吉首市| 岳普湖县| 财经| 静海县| 贡觉县| 同江市| 阿拉尔市| 民勤县| 伊川县| 花莲市| 三江| 武平县| 迁安市| 汕尾市| 克东县| 三原县| 临汾市| 广汉市| 宜兰市| 青州市|