【发布时间】:2021-07-16 20:46:36
【问题描述】:
我有一个简短的 Go 程序,它为多个包运行 go list -json 命令,将每次运行命令的输出存储在 json.RawMessage 中,将每个 json.RawMessage 附加到一段 json.RawMessages 中,然后将每个 json.RawMessages 连接在一起并压缩 json 后,将结果返回给服务器。但是,当我运行 json.Compact 时会产生一条错误消息,我无法找到它的来源。谷歌搜索这条错误消息表明,大多数遇到它的人——无论是无效的, 还是其他字符——都很难找到它的来源。
invalid character ',' looking for beginning of value
带有 cmets 的代码可以在这里查看on play.golang.org(虽然它不会在那里运行),也可以在下面查看。
问题:能否解释一下这个错误的来源以及如何预防?
(请注意,某些软件包仅用于测试目的)
package main
import (
"expvar"
"encoding/json"
"bytes"
"fmt"
"github.com/go-martini/martini"
"github.com/zenazn/goji"
"github.com/zenazn/goji/web"
"go/build"
"log"
"math/rand"
"net/http"
_ "net/http/pprof"
"os/exec"
)
type myType struct {
J []json.RawMessage
}
var pack map[string]string
type GoList struct {
Imports []string
}
type Import struct {
Dir string
ImportPath string
Name string
Target string
Standard bool
Root string
GoFiles []string
Imports []string
Deps []string
}
const contentTypeJSON = "application/json"
func main() {
http.HandleFunc("/importgraph", func(w http.ResponseWriter, r *http.Request) { importGraph(w, r) })
http.HandleFunc("/", handler)
http.ListenAndServe(":8080", nil)
}
func handler(w http.ResponseWriter, r *http.Request) {
fmt.Println("Inside handler")
fmt.Fprintf(w, "Hello world from my Go program!")
}
func importGraph(w http.ResponseWriter, r *http.Request) {
pack = make(map[string]string)
var t myType
cmd := exec.Command("go", "list", "-json")
stdout, err := cmd.Output()
if err != nil {
println(err.Error())
return
}
var list GoList
err = json.Unmarshal(stdout, &list)
for _, d := range list.Imports {
//get the imports for each of the packages listed by go list -json
t.imports(d)
}
var buff bytes.Buffer
//concatenate the separate json.RawMessages together into json
buff.WriteByte('[')
for i, j := range t.J {
if i != 0 {
buff.WriteByte(',')
}
buff.Write([]byte(j))
}
buff.WriteByte(']')
var buffer bytes.Buffer
if err := json.Compact(&buffer, buff.Bytes()); err != nil {
println(err.Error()) //error message: invalid character ',' looking for beginning of value
return
}
w.Header().Set("Content-Type", contentTypeJSON)
w.Write(buffer.Bytes())
}
func (myObj *myType) imports(pk string) error {
cmd := exec.Command("go", "list", "-json", pk)
stdout, _ := cmd.Output()
pack[pk] = pk
var deplist Import
json.Unmarshal(stdout, &deplist)
var newj json.RawMessage
json.Unmarshal(stdout, &newj)
myObj.J = append(myObj.J, newj)
for _, imp := range deplist.Imports {
if _, ok := pack[imp]; !ok {
myObj.imports(imp) //recursive call to get the imports of the imports etc
}
}
return nil
}
【问题讨论】:
-
有关该错误的更多详细信息?行号/任何其他跟踪?
-
go list命令是go/build 包的包装。我建议从您的应用程序中调用build.DefaultContext.Import(path, "", 0)来获取导入,而不是执行go list命令。 -
@Momer 它没有给出行号,也没有给出踪迹。有没有办法创建跟踪?
-
@thundercat 我想要 go list 命令的 json 输出。你能建议我如何将 go build 转为 json 吗?
-
以下是如何将具有给定路径的包的导入编码为 JSON:
p, err := build.DefaultContext.Import(path, "", 0); jsonBytes, err := json.Marshal(p.Imports)一般策略是建立一个与您想要的 JSON 值相对应的 Go 值,然后调用 json.Marshal(五)。
标签: go