go - 如何将curl通过管道传输到Go程序中?

标签 go curl pipe

我想写一个Go小程序,用来美化json数据。当我使用文件时它已经可以工作了。这是代码:

package main

import (
    "bufio"
    "fmt"
    "github.com/Jeffail/gabs"
    "log"
    "os"
)

func main() {
    info, err := os.Stdin.Stat()
    if err != nil {
        log.Fatal(err)
    }

    if info.Mode()&os.ModeCharDevice != 0 || info.Size() <= 0 {
        fmt.Println("The command is intended to work with pipes.")
        fmt.Println("cat file.json | prettyjson")
        return
    }

    reader := bufio.NewReader(os.Stdin)


    input, err := reader.ReadBytes('\n')
    if err != nil {
        log.Fatal()
    }

    jsonParsed, err := gabs.ParseJSON(input)
    if err != nil {
        log.Fatal("couldn't parse json")
    }

    fmt.Println(fmt.Println(jsonParsed.StringIndent("", "  ")))
}

如果我像这样使用curl运行此代码:

curl -s "https://min-api.cryptocompare.com/data/top/exchanges?fsym=BTC&tsym=USD" | prettyjson

我得到:(23) 写入正文失败

我在this post中看到在curl写入所有数据之前管道将被关闭,但是如何优化我的Go程序以等待curl完成?

最佳答案

关于OP源代码,我会考虑更改条件来检测管道的存在。

正如https://stackoverflow.com/a/43947435/4466350中已经提供的那样正确的条件不需要检查输入的长度。考虑一下,这完全有道理,因为您可以打开标准输入而不在其上写入数据。

除了所提出的解决方案对于它试图实现的目标来说似乎毫无用处的复杂性之外,还可以漂亮地打印 json 输入。

我发现使用标准库足以实现给定测试用例的目标。

关于问题...但是我如何优化我的Go程序以等待curl完成?,OP似乎不理解文件描述符的工作方式。事实上,这个问题甚至不正确,因为理论上该进程可以保持事件状态,但主动决定关闭 Stdin。 OP 对进程的活跃度不感兴趣,相反,他应该在读取 Stdin 时简单地查找 EOF 信号,表明感兴趣的数据已正确发送。

无论如何,一个简单的解决方案看起来像这样,用 json 解码器包装 stdin,循环直到 eof 或发生错误,对于每个解码的数据,用 stdout 包装器将其编码为 json,再次出现错误中断。

package main

import (
    "encoding/json"
    "fmt"
    "io"
    "log"
    "os"
)

func main() {
    info, err := os.Stdin.Stat()
    if err != nil {
        log.Fatal(err)
    }

    if info.Mode()&os.ModeCharDevice != 0 {
        fmt.Println("The command is intended to work with pipes.")
        fmt.Println("cat file.json | prettyjson")
        return
    }

    dec := json.NewDecoder(os.Stdin)
    enc := json.NewEncoder(os.Stdout)
    enc.SetIndent("", "  ")

    for {
        data := map[string]interface{}{}
        if err := dec.Decode(&data); err != nil {
            if err == io.EOF {
                break
            }
            log.Fatalf("decode error %v", err)
        }
        if err := enc.Encode(data); err != nil {
            log.Fatalf("encod error %v", err)
        }
    }
}

关于go - 如何将curl通过管道传输到Go程序中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53122331/

相关文章:

php - 将 cURL 用于 Amazon Associates 报告...可能吗?

node.js - 未知方法 process.openStdin()

c - 如何在循环中使用管道,我的正确吗?

json - gzip 压缩到 http responseWriter

Golang - 将可变长度数组映射到结构

php - 使用 XAMPP for Windows 为 PHP 启用 cURL 库

angular - ngx-pipes 按多个条件过滤

postgresql - 使用 xo 从 postgres 数据库表模式生成 DTO 结构

go - 提供静态内容并处理 404 not found with Gorilla toolkit

php 服务器找不到 curl.so