2015-03-24 6 views
5

मेरे पास एक छोटा गो प्रोग्राम है जो go list -json कई संकुलों के लिए आदेश चलाता है, एक जेसन में कमांड के प्रत्येक रन के आउटपुट को स्टोर करता है। RawMessage , प्रत्येक जेसन को जोड़ता है। जेसन के एक टुकड़े में रौज मैसेज। रॉ मैसेज, और उसके बाद प्रत्येक जेसन को संयोजित करने के बाद सर्वर को परिणाम देता है। एक साथ संदेश और जेसन को कॉम्पैक्ट करना। हालांकि, एक त्रुटि संदेश है जो उत्पादित होता है जब मैं json.Compact चलाता हूं कि मैं स्रोत का पता नहीं लगा सकता। इस त्रुटि संदेश को गुगल करने से पता चलता है कि ज्यादातर लोग इसे सामना करते हैं - चाहे वह अमान्य , या किसी अन्य चरित्र के लिए है - इसके स्रोत को ढूंढने में कठिन समय है। भी नीचे (हालांकि यह वहाँ नहीं चलेंगे) और"अमान्य चरित्र ',' मूल्य की शुरुआत की तलाश 'त्रुटि संदेश

invalid character ',' looking for beginning of value 

टिप्पणी के साथ कोड यहाँ 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 

} 
+0

त्रुटि के बारे में कोई और जानकारी? रेखा संख्या/कोई अतिरिक्त निशान? – Momer

+1

'go list' कमांड [go/build] (http://godoc.org/go/build) पैकेज के चारों ओर एक रैपर है। मैं 'go list' कमांड को निष्पादित करने के बजाय आयात प्राप्त करने के लिए अपने एप्लिकेशन से 'build.DefaultContext.Import (पथ," ", 0) 'कॉल करने का सुझाव देता हूं। –

+0

@ मॉमर यह एक लाइन नंबर नहीं देता है, न ही एक निशान। क्या कोई निशान बनाने का कोई तरीका है? – Leahcim

उत्तर

8

सबसे पहले, के रूप में टिप्पणी की गई है, क्या आप वाकई go/build पैकेज सीधे नहीं बल्कि उपयोग नहीं कर सकते go list चलाने की तुलना में कर रहे हैं?

मैं HTTP हैंडलरों के अंदर println (या fmt.Println) का उपयोग नहीं करूंगा। log.Println का उपयोग करना और/या ResponseWriter में त्रुटि प्राप्त करना बेहतर है। साथ ही, log.Fatal के साथ अपने ListenAndServe कॉल को लपेटना अच्छा विचार है।

error मानों को प्रिंट/लॉगिंग करते समय आप err का उपयोग कर सकते हैं, err.Error() रखने की कोई आवश्यकता नहीं है।

आगे, जब आप वास्तव में त्रुटि संदेश की रिपोर्टिंग/लॉगिंग करने से कुछ और अधिक विस्तृत करना चाहते हैं तो आप इसके प्रकार और अन्य जानकारी को देख सकते हैं। उदाहरण के लिए, log.Printf("verbose error info: %#v", err) देता है:

&json.SyntaxError{msg:"invalid character ',' looking for beginning of value", Offset:0} 

मैं इस कोशिश की क्योंकि मैं जानता हूँ कि json पैकेज में अतिरिक्त जानकारी के साथ विभिन्न प्रकार के त्रुटि देता है और मुझे उम्मीद थी ऑफसेट मूल्य मदद मिलेगी। यदि यह तो किया गया था कुछ इस तरह उपयोगी हो सकते:

if err := json.Compact(…) { 
    if err != nil { 
     log.Println("json.Compact:", err) 
     if serr, ok := err.(*json.SyntaxError); ok { 
      log.Println("Occurred at offset:", serr.Offset) 
      // … something to show the data in buff around that offset … 
     } 
    } 
} 

लेकिन शून्य ऑफसेट उपयोगी :(नहीं है

इसलिए हालांकि यह आपकी पहचान नहीं करती समस्या उम्मीद है कि यह कुछ मदद की हो सकती है अपने आगे की जांच पड़ताल करने के लिए

संपादित करें:।

तो जोड़ने के बाद:

log.Println("Write file:", ioutil.WriteFile("data.json", buff.Bytes(), 0600)) 
उपरोक्त त्रुटि हैंडलिंग ब्लॉक करने के लिए

मैं तो उसके एवज में फ़ाइल पर एक JSON सत्यापनकर्ता भाग गया और यह इस टुकड़े की पहचान:

 "XTestImports": [ 
       "io", 
       "log", 
       "net" 
     ] 
},,{ 
     "Dir": "/usr/local/go/src/mime", 
     "ImportPath": "mime", 
     "Name": "mime", 

नोट डबल ,,

यह आपको बताएगा कि आपके कोड में त्रुटि क्या है। लेकिन यदि नहीं, तो आपको t.J या जब आप इसे बनाते हैं, तो आपको खाली प्रविष्टियों को छोड़ना होगा। बाद में बेहतर है और बस शामिल है:।

if len(newj) > 0 { 
     myObj.J = append(myObj.J, newj) 
    } 

(जहां btw आप json.Unmarshal से त्रुटियों की जांच नहीं करते हैं तो यह स्पष्ट नहीं है कि अगर कभी खाली माना जाता है या अगर यह एक पूर्ववर्ती त्रुटि के कारण खाली है कभी भी त्रुटि रिटर्न को अनदेखा करें!)

+0

के अंत में '' 'हो सकता है, मैं चाहता हूं कि जेएसन आउटपुट सूची-जेसन का आउटपुट हो, अन्यथा मुझे मैन्युअल रूप से जेसन बनाना होगा और मुझे यकीन नहीं है कि कैसे ऐसा करने में (यह मेरा पहला जाना प्रोजेक्ट है) – Leahcim

+0

@ लेहसीम ने एक कूड़े की जांच की और समस्या को पाया। मैं आपके लिए बाकी उत्तर यहां छोड़ दूंगा क्योंकि इससे आपको यह समझने में मदद करनी चाहिए कि आप इन चीज़ों को स्वयं कैसे पा सकते हैं। –

+0

यह बहुत दिलचस्प है (आपको समस्या कैसे मिली) लेकिन मुझे पूरी तरह से यकीन नहीं है कि मैं समझता हूं कि यह किस विशेषता का विरोध कर रहा है। Json.Compact \ n और \ t वर्णों को निकालना था, क्या वे समस्या हैं? मैं अपने कंप्यूटर पर अपने कोड की कोशिश करूंगा – Leahcim

2

मुझे एक गो प्रोग्राम में एक ही त्रुटि संदेश का सामना करना पड़ा, लेकिन त्रुटि संदेश HTTP प्रतिक्रिया त्रुटि में था, HTML प्रारूप में जब मेरा HTTP प्रतिक्रिया पार्सर JSON की अपेक्षा करता था।

मेरे लिए, समाधान Content-Type शीर्षलेख application/json पर सेट करने के लिए मेरा अनुरोध बदलना था। आप यह कैसे करते हैं इस पर निर्भर करता है कि आप कौन सी http क्लाइंट लाइब्रेरी का उपयोग कर रहे हैं; अगर आपके पास http.Header कोर प्रकार तक पहुंच है, तो आप हेडर को .Set(...) से सेट कर सकते हैं।

मुझे एहसास है कि मेरे लिए इस फिक्स का दायरा मूल प्रश्न पर लागू नहीं हो सकता है, लेकिन मैं पहले यहां आने के बाद आया था और सोचा था कि यह दूसरों की मदद करेगा, क्योंकि संदेश पहली नज़र में विशेष रूप से स्पष्ट नहीं था। संकेत यह है कि अमान्य < वर्ण त्रुटि/प्रतिक्रिया में पहला HTML वर्ण है, जो संभवतः अनुरोध प्रकार का परिणाम application/json पर सेट नहीं किया जा रहा है, इस प्रकार सर्वर गैर-JSON प्रतिक्रिया के साथ प्रतिक्रिया करता है।

संबंधित मुद्दे