go - 无法从恐慌中恢复 - 完全跳过延迟
问题描述
将 io.Copy 与无效的 writer 一起使用时,我会感到恐慌——这是意料之中的。但是,在这种情况下,我无法恢复。我的延迟恢复完全被绕过了。这是代码:
package main
import (
"context"
"fmt"
"io"
"log"
"os"
"runtime"
"runtime/debug"
"cloud.google.com/go/storage"
)
func main() {
var (
ctx = context.Background()
fromFile = "blah.txt"
bucket = "blah-bucket"
path = "blah-path"
)
defer func() {
if result := recover(); result != nil {
buf := make([]byte, 1<<16)
length := runtime.Stack(buf, false)
log.Fatalf("PANIC RECOVER: %v\nSTACK: \n%s", result, buf[:length])
debug.PrintStack()
}
}()
err := FakeUpload(ctx, fromFile, bucket, path)
if err != nil {
fmt.Println(err)
}
fmt.Println("HELLO")
}
func FakeUpload(ctx context.Context, fromFile, toBucket, toPath string) (err error) {
var (
file *os.File
client *storage.Client
wc *storage.Writer
)
defer func() {
for _, c := range []io.Closer{wc, file} {
if c != nil {
err = c.Close()
if err != nil {
return
}
}
}
}()
file, err = os.Open(fromFile)
if err != nil {
err = fmt.Errorf("problem opening file %v: %v", fromFile, err)
return
}
wc = client.Bucket(toBucket).Object(toPath).NewWriter(ctx)
_, err = io.Copy(wc, file) // THE UNRECOVERABLE PANIC HAPPENS HERE
return
}
恐慌是:
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x0 addr=0x0 pc=0x9e0fa8]
goroutine 21 [running]:
cloud.google.com/go/storage.(*Writer).open.func1(0xc000161200, 0xc0002721e0, 0xc000150388, 0xc000290e20, 0x1, 0x1)
C:/Users/xxxx/go/pkg/mod/cloud.google.com/go/storage@v1.14.0/writer.go:128 +0x248
created by cloud.google.com/go/storage.(*Writer).open
C:/Users/xxxx/go/pkg/mod/cloud.google.com/go/storage@v1.14.0/writer.go:118 +0x6ce
Process exiting with code: 0
module main
go 1.15
require cloud.google.com/go/storage v1.14.0
go version go1.15.10 windows/amd64
踢球者是,如果它在其他地方恐慌,例如我指向一个无效文件,它会恐慌,并且延迟恢复会正确捕获它。
这让我很困惑。任何的想法?
解决方案
正如您在上面的评论中所读到的,答案是cloud.google.com/go/storage
作者正在创建一个 goroutine,并将恐慌投入其中。GO 不允许你从另一个 goroutine 中恢复。
推荐阅读
- google-app-engine - Google 服务帐户日志
- salesforce - lwc-services 未被识别为内部或外部命令
- c# - 如何在 C# 中使用 DataGridView 值作为保存和加载控件?
- flutter - Flutter - Firebase 电子邮件格式错误,为空
- bluetooth-lowenergy - iBeacon 名称未显示在 ESP32 BLE 扫描仪中
- swift - 将 ARFaceGeometry 保存到 OBJ 文件
- vue.js - 找不到Vue js路由404和资产
- laravel - Laravel 说在表单中给出动作时缺少必需的参数
- r - 如何以一定次数重复堆叠同一行
- google-apps-script - 如何在谷歌电子表格中 B 列的每个填充单元格中获取文本