为了账号安全,请及时绑定邮箱和手机立即绑定

如何通过管道将 curl 导入 Go 程序?

如何通过管道将 curl 导入 Go 程序?

Go
桃花长相依 2023-05-04 17:41:00
我想写一个小的 Go 程序,我可以用它来美化 json 数据。当我使用文件时它已经工作了。这是代码:package mainimport (    "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我在这篇文章中看到在curl 可以写入所有数据之前管道正在关闭,但是我如何优化我的 Go 程序以等待 curl 完成?
查看完整描述

1 回答

?
有只小跳蛙

TA贡献1824条经验 获得超8个赞

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

正确的条件不需要检查输入的长度。考虑一下,这完全是有道理的,因为您可以在不写入数据的情况下打开标准输入。

除了所提出的解决方案对于它试图实现的目标而言似乎毫无用处的复杂性,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)

        }

    }

}


查看完整回答
反对 回复 2023-05-04
  • 1 回答
  • 0 关注
  • 100 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信