2015-02-05 54 views
2

我正在嘗試在Go中編寫一個小型web應用程序,其中用戶以多部分形式上傳gzip文件。該應用程序解壓縮並解析文件並將一些輸出寫入響應。不過,當我開始寫入響應時,我仍然遇到輸入流看起來已損壞的錯誤。不寫入響應可以解決問題,就像讀取非壓縮輸入流一樣。下面是一個例子HTTP處理程序:Golang寫入http響應中斷輸入讀數?

func(w http.ResponseWriter, req *http.Request) { 

//Get an input stream from the multipart reader 
//and read it using a scanner 
multiReader, _ := req.MultipartReader() 
part, _ := multiReader.NextPart() 
gzipReader, _ := gzip.NewReader(part) 
scanner := bufio.NewScanner(gzipReader) 

//Strings read from the input stream go to this channel  
inputChan := make(chan string, 1000) 

//Signal completion on this channel 
donechan := make(chan bool, 1) 

//This goroutine just reads text from the input scanner 
//and sends it into the channel 
go func() { 
    for scanner.Scan() { 
     inputChan <- scanner.Text() 
    }  
    close(inputChan) 
}() 

//Read lines from input channel. They all either start with # 
//or have ten tab-separated columns 
go func() { 
    for line := range inputChan { 
     toks := strings.Split(line, "\t") 
     if len(toks) != 10 && line[0] != '#' { 
      panic("Dang.") 
     } 
    } 
    donechan <- true 
}() 

//periodically write some random text to the response 
go func() { 
    for { 
     time.Sleep(10*time.Millisecond)  
     w.Write([]byte("write\n some \n output\n")) 
    } 
}() 

//wait until we're done to return 
<-donechan 
} 

古怪,每次因爲它總是會遇到少於10個令牌的線,這個時間碼恐慌在不同的地點,每次雖然。註釋寫入響應的行可以解決問題,就像讀取非壓縮的輸入流一樣。我錯過了明顯的東西嗎?如果從gzip文件讀取而不是純文本格式的文件,爲什麼要寫入響應中斷?爲什麼它會打破?

回答

1

HTTP協議不是全雙工的:它是基於請求響應的。讀完輸入後,您只應發送輸出。

在您的代碼中,您在頻道上使用forrange。這將嘗試讀取通道,直到它關閉,但您永遠不會關閉inputChan

如果你從來沒有接近inputChan,下面一行則永遠無法實現:

donechan <- true 

也因此從donechan塊接收:

<-donechan 

你必須關閉inputChan當達到EOF:

go func() { 
    for scanner.Scan() { 
     inputChan <- scanner.Text() 
    }  
    close(inputChan) // THIS IS NEEDED 
}() 
+0

謝謝!關閉inputChan的好處。代碼只是我能夠生產的最小的例子,證明了這個問題。我將編輯帖子... – homesalad