我想编写一个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程序以等待卷曲完成?
答案 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)
}
}
}