2015-02-05 31 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