如何将curl导入Go程序?

时间:2018-11-02 16:19:36

标签: 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) Failed writing body

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

1 个答案:

答案 0 :(得分:2)

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

https://stackoverflow.com/a/43947435/4466350中已经提供的那样,正确的条件不需要检查输入的长度。考虑一下,这完全有意义,因为您可能会打开stdin而无需在上面写数据。

除了所提出的解决方案,它对于试图实现的目的来说似乎是无用的复杂,它漂亮地打印了json输入。

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

关于问题...but how do I optimize my Go program to wait until curl is done?,看来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)
        }
    }
}