91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

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

發布時間:2023-03-08 10:47:01 來源:億速云 閱讀:107 作者:iii 欄目:開發技術

這篇“Golang pipe在不同場景下怎么遠程交互”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“Golang pipe在不同場景下怎么遠程交互”文章吧。

Pipe介紹

pipe實現從一個進程重定向至另一個進程,它是雙向數據通道,用于實現進行間通信。

io.Pipe函數創建內存同步通道,用于連接io.Reader和io.Writer. 本文示例使用環境為:

go version
go version go1.19.3 linux/amd64

Go pipe簡單示例

在實現遠程交互之前,先看下面簡單示例,演示如何使用io.Pipe函數:

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

首先創建pipe,然后在協程中給管道的writer寫數據,然后使用io.Copy函數從管道Reader中拷貝數據至標準輸出:

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

在協程中寫數據是因為每次寫PipeWriter都阻塞直到PipeReader完全消費了數據。

運行程序:

go run main.go 
Hello there

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

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行并輸出到控制臺,運行程序,輸出結果如下:

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

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

http請求處理中使用管道

下面示例展示在http請求處理中使用管道。運行date命令,通過HTTP輸出結果,可以實現元從查看命令執行結果。

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

關鍵代碼為創建管道,并把PipeWriter賦給命令的標準輸出和標準錯誤。

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

go io.Copy(w, pr)

然后在協程中拷貝PipeReader至http.ResponseWriter.最后運行程序查看結果:

$ go run handler.go 
server started on port 8080

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

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

修改上面程序,把命令作為參數,即可實現遠程交互。下面我們看看如何利用管道給輸入端寫入數據,包括http請求和命令的標準輸入。

利用管道提交post請求json數據

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

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

上面示例實現給post請求提交json數據,并讀取響應內容。

首先定義管道,然后在協程中給管道Writer寫入json數據:

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

然后把管道Reader作為參數傳入請求:

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

最后讀取響應內容:

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

運行程序輸出結果:

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"
  }, 
  // 省略...
}

通過管道讀標準輸入

下面示例利用管道從標準輸入讀取數據,并打印數據及數據字節數、塊數:

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

然后創建4kb緩沖區,從標準輸入讀數據至緩沖區。然后計算塊數和字節數,最后答應緩沖區內容。

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

Bytes: 43 Chunks: 1

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

Go Stat

Stat函數返回FileInfo結構體,描述文件信息。我們可以利用其檢查數據是否來自終端。

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

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

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

獲取到標準輸入的FileInfo結構體后進行判斷:

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

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

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

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

以上就是關于“Golang pipe在不同場景下怎么遠程交互”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

五家渠市| 班戈县| 金沙县| 宜宾县| 阿勒泰市| 和政县| 延寿县| 兴城市| 同心县| 桃江县| 共和县| 东阳市| 罗甸县| 即墨市| 陇川县| 招远市| 登封市| 民勤县| 精河县| 东辽县| 建昌县| 富锦市| 淳安县| 广水市| 巩义市| 金寨县| 临颍县| 宜城市| 芜湖市| 中阳县| 子洲县| 东方市| 阿拉尔市| 南漳县| 阳信县| 清河县| 普格县| 仪征市| 元氏县| 全南县| 冕宁县|