英文:
Golang: panic: runtime error: invalid memory address or nil pointer dereference
问题
当我上传文件到我的Go应用程序时,遇到了一个恐慌。
panic: 运行时错误:无效的内存地址或空指针解引用
/Users/bob/Projects/go/src/github.com/zenazn/goji/web/middleware/recoverer.go:24 (0xbaf5b)
func.006: debug.PrintStack()
/usr/local/go/src/pkg/runtime/panic.c:248 (0x1043d)
panic: runtime·newstackcall(d->fn, (byte*)d->args, d->siz);
/usr/local/go/src/pkg/runtime/panic.c:552 (0x10eed)
panicstring: runtime·panic(err);
/usr/local/go/src/pkg/runtime/os_darwin.c:454 (0xfb8e)
sigpanic: runtime·panicstring("invalid memory address or nil pointer dereference");
/usr/local/go/src/pkg/mime/multipart/multipart.go:223 (0xb6801)
(*Reader).NextPart: if r.currentPart != nil {
/Users/bob/Projects/go/src/github.com/app/controllers/company_sheet_controller.go:32 (0x2ee18)
NewCompanySheet: part, err := mr.NextPart()
/usr/local/go/src/pkg/net/http/server.go:1235 (0x44f00)
HandlerFunc.ServeHTTP: f(w, r)
/Users/bob/Projects/go/src/github.com/zenazn/goji/web/router.go:113 (0x6bc0a)
这个方法处理来自多部分表单的上传,提取文件内容和边界数据。请求的r.FormFile
方法用于设置文件和头部。为了从POST请求中获取额外的数据,我使用了r.MultipartReader
。从错误描述中我看到,在使用r.FormFile
时,r
已经被声明为ParseMultipartForm
。当我单独执行不同的请求方法时,没有出现错误。r.FormFile
和r.MultipartReader
在隔离的情况下工作正常。我不能混合使用这两种请求方法吗?
func Upload(r *http.Request) {
file, header, err := r.FormFile("file")
ErrorCheck(err)
mr, err := r.MultipartReader()
ErrorCheck(err)
part, err := mr.NextPart()
ErrorCheck(err)
var b bytes.Buffer
io.CopyN(&b, part, int64(1<<20))
fmt.Println(b.String())
defer file.Close()
}
英文:
When uploading a file to my go app, I encounter a panic.
panic: runtime error: invalid memory address or nil pointer dereference
/Users/bob/Projects/go/src/github.com/zenazn/goji/web/middleware/recoverer.go:24 (0xbaf5b)
func.006: debug.PrintStack()
/usr/local/go/src/pkg/runtime/panic.c:248 (0x1043d)
panic: runtime·newstackcall(d->fn, (byte*)d->args, d->siz);
/usr/local/go/src/pkg/runtime/panic.c:552 (0x10eed)
panicstring: runtime·panic(err);
/usr/local/go/src/pkg/runtime/os_darwin.c:454 (0xfb8e)
sigpanic: runtime·panicstring("invalid memory address or nil pointer dereference");
/usr/local/go/src/pkg/mime/multipart/multipart.go:223 (0xb6801)
(*Reader).NextPart: if r.currentPart != nil {
/Users/bob/Projects/go/src/github.com/app/controllers/company_sheet_controller.go:32 (0x2ee18)
NewCompanySheet: part, err := mr.NextPart()
/usr/local/go/src/pkg/net/http/server.go:1235 (0x44f00)
HandlerFunc.ServeHTTP: f(w, r)
/Users/bob/Projects/go/src/github.com/zenazn/goji/web/router.go:113 (0x6bc0a)
This method handles an upload from a multipart form, extracting the file contents and boundary data. The r.FormFile
method on request is used to set file and header. And in order to pull the additional data from the post, I use r.MultipartReader
. From the error description I see r
is already declared as ParseMultipartForm
when using r.FormFile
. When executing the function with the different request methods individually, I receive no errors. r.FormFile
and r.MultipartReader
work fine isolated. Am I unable to mix the two request methods?
func Upload(r *http.Request) {
file, header, err := r.FormFile("file")
ErrorCheck(err)
mr, err := r.MultipartReader()
ErrorCheck(err)
part, err := mr.NextPart()
ErrorCheck(err)
var b bytes.Buffer
io.CopyN(&b, part, int64(1<<20))
fmt.Println(b.String())
defer file.Close()
}
答案1
得分: 2
你在函数的开头调用了FormFile()。
这会调用ParseMultipartForm()(参见Request.FormFile),它会填充你的http.Request的MultipartForm字段。
现在,MultipartReader()的文档说明如果你想将数据作为流进行处理,应该使用MultipartReader() 而不是 ParseMultipartForm()。
从源代码可以看出,如果MultipartForm字段已经设置,MultipartReader()会返回一个错误。
所以回答你的问题:不,你不能在同一个请求中同时使用这两个函数。
另外,你的
defer file.Close()
应该在检查FormFile()是否返回错误之后立即执行,否则在函数发生恐慌时,文件将在垃圾回收之前不会被关闭。
英文:
You are calling FormFile() at the beginning of your function.
This calls ParseMultipartForm() (see Request.FormFile) which populates the MultipartForm field of your http.Request.
Now the documentation for MultipartReader() states that you should use MultipartReader() instead of ParseMultipartForm() if you want to process the data as stream.
Looking at the source MultipartReader() returns an error if the MultipartForm field was already set.
So to answer your question: No, you can't use both functions for the same request.
Also your
defer file.Close()
should be right after you checked for an error from FormFile(), otherwise the file won't be closed before Garbage Collection, when your function panics.
1: http://golang.org/pkg/net/http/#Request.FormFile "Request.FormFile"
2: http://golang.org/pkg/net/http/#Request "http.Request"
3: http://golang.org/pkg/net/http/#Request.MultipartReader "MultipartReader"
4: http://golang.org/src/net/http/request.go?s=10494:10556#L286 "source of MultipartReader()"
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论