使用Golang的goexif包时发生panic问题

使用Golang的goexif包时发生panic问题 详细 panic 追踪信息 -

	goroutine 5 [running]:
runtime/debug.Stack(0xc42004f208, 0xb71060, 0x1222960)
	/usr/local/go/src/runtime/debug/stack.go:24 +0xa7
Upload-Image-API/services/controllers/uploadimage.UploadImages.func1()
	/home3/indiamart/public_html/go/src/Upload-Image-API/services/controllers/uploadimage/uploadimage.go:28 +0x48
panic(0xb71060, 0x1222960)
	/usr/local/go/src/runtime/panic.go:491 +0x283
github.com/rwcarlsen/goexif/mknote.(*nikonV3).Parse(0x1289980, 0xc4201adb90, 0x0, 0x0)
	/home3/indiamart/public_html/go/src/github.com/rwcarlsen/goexif/mknote/mknote.go:58 +0x2f4
github.com/rwcarlsen/goexif/exif.Decode(0x1232ae0, 0xc42000e1a0, 0x2, 0x0, 0x0)
	/home3/indiamart/public_html/go/src/github.com/rwcarlsen/goexif/exif/exif.go:301 +0x666
Upload-Image-API/services/utils.GetMetaDataOfImage(0xc420076600, 0x77, 0xb26720, 0xc420019310, 0xc420151888)
	/home3/indiamart/public_html/go/src/Upload-Image-API/services/utils/utils.go:204 +0x1ed
Upload-Image-API/services/controllers/uploadimage.UploadImages(0x12397e0, 0xc42015c000, 0xc4200fc500)
	/home3/indiamart/public_html/go/src/Upload-Image-API/services/controllers/uploadimage/uploadimage.go:170 +0x1c33
net/http.HandlerFunc.ServeHTTP(0xc518b8, 0x12397e0, 0xc42015c000, 0xc4200fc500)
	/usr/local/go/src/net/http/server.go:1918 +0x44
github.com/gorilla/mux.(*Router).ServeHTTP(0xc4201c1f80, 0x12397e0, 0xc42015c000, 0xc4200fc500)
	/home3/indiamart/public_html/go/src/github.com/gorilla/mux/mux.go:162 +0xed
github.com/gorilla/handlers.(*cors).ServeHTTP(0xc4201a9830, 0x12397e0, 0xc42015c000, 0xc4200fc300)
	/home3/indiamart/public_html/go/src/github.com/gorilla/handlers/cors.go:52 +0xa77
net/http.serverHandler.ServeHTTP(0xc4201ae4e0, 0x12397e0, 0xc42015c000, 0xc4200fc300)
	/usr/local/go/src/net/http/server.go:2619 +0xb4
net/http.(*conn).serve(0xc420158000, 0x1239e20, 0xc42005aac0)
	/usr/local/go/src/net/http/server.go:1801 +0x71d
created by net/http.(*Server).Serve
	/usr/local/go/src/net/http/server.go:2720 +0x288

我的代码-

func GetMetaDataOfImage(filepath string) (map[string]interface{}, error) {
var metaInformationOfImage = make(map[string]interface{})
metaInformationOfImage["Timestamp"] = ""
metaInformationOfImage["Latitude"] = ""
metaInformationOfImage["Longitude"] = ""
f, err := os.Open(filepath)
if err != nil {
return metaInformationOfImage, err
}
exif.RegisterParsers(mknote.All...)
x, err := exif.Decode(f)
if err != nil {
return metaInformationOfImage, err
}
timestamp, err := x.DateTime()
if err != nil {
return metaInformationOfImage, err
}
metaInformationOfImage["Timestamp"] = timestamp.Format("02-01-06")
lat, long, err := x.LatLong()
if err != nil {
return metaInformationOfImage, err
}
metaInformationOfImage["Latitude"] = fmt.Sprintf("%g", lat)
metaInformationOfImage["Longitude"] = fmt.Sprintf("%g", long)
return metaInformationOfImage, err
}

更多关于使用Golang的goexif包时发生panic问题的实战教程也可以访问 https://www.itying.com/category-94-b0.html

2 回复

嘿,尼米什,

你能在代码中加上行号吗? 而且你还没有显示panic的实际错误信息,只有堆栈跟踪。你能把这个也展示出来吗?

更多关于使用Golang的goexif包时发生panic问题的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


从panic追踪信息来看,问题出现在goexif/mknote包的nikonV3.Parse方法中(第58行)。这是一个第三方库在处理特定图像文件时的内部panic,可能是由于图像EXIF数据格式不符合预期导致的。

在你的代码中,当调用exif.Decode(f)时,如果遇到某些特定的Nikon相机拍摄的图像,goexif库可能会在处理makernote数据时发生panic。由于这是库内部的panic,需要通过recover机制来捕获并处理。

以下是修复后的代码示例:

func GetMetaDataOfImage(filepath string) (map[string]interface{}, error) {
    var metaInformationOfImage = make(map[string]interface{})
    metaInformationOfImage["Timestamp"] = ""
    metaInformationOfImage["Latitude"] = ""
    metaInformationOfImage["Longitude"] = ""
    
    f, err := os.Open(filepath)
    if err != nil {
        return metaInformationOfImage, err
    }
    defer f.Close()
    
    // 使用defer和recover捕获panic
    defer func() {
        if r := recover(); r != nil {
            err = fmt.Errorf("panic occurred during EXIF decoding: %v", r)
        }
    }()
    
    exif.RegisterParsers(mknote.All...)
    x, err := exif.Decode(f)
    if err != nil {
        return metaInformationOfImage, err
    }
    
    timestamp, err := x.DateTime()
    if err == nil {
        metaInformationOfImage["Timestamp"] = timestamp.Format("02-01-06")
    }
    
    lat, long, err := x.LatLong()
    if err == nil {
        metaInformationOfImage["Latitude"] = fmt.Sprintf("%g", lat)
        metaInformationOfImage["Longitude"] = fmt.Sprintf("%g", long)
    }
    
    return metaInformationOfImage, err
}

另外,你还可以在调用这个函数的地方添加panic恢复机制:

func UploadImages(w http.ResponseWriter, r *http.Request) {
    defer func() {
        if r := recover(); r != nil {
            log.Printf("Recovered from panic: %v", r)
            http.Error(w, "Internal server error", http.StatusInternalServerError)
        }
    }()
    
    // 原有的处理逻辑
    metadata, err := GetMetaDataOfImage(filepath)
    if err != nil {
        // 处理错误
    }
    // ... 其他代码
}

这样处理可以确保即使goexif库内部发生panic,你的应用程序也不会崩溃,而是能够优雅地处理错误情况。

回到顶部