You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Golang+Cobra框架扫描文件路径触发空指针Panic问题

问题描述

使用Go语言的Cobra框架开发一款客户端,用于向传输服务上传文件,需求支持自定义默认下载文件夹。但在检查目标路径是否为存在的文件夹、是否具备写入权限时触发了空指针Panic,场景是在macOS系统中使用拖拽功能输入路径。

原代码

var dldpath string
inquire.Query().Input(&dldpath, "Chemin du dossier de téléchargement ", nil).Exec()

println("le chemin est : ", dldpath)

if len(dldpath) == 0 {
    fmt.Println(chalk.Red, "Erreur : Vous devez spécifier un dossier à téléverser")
    os.Exit(0)
}
dir, err := os.Stat(dldpath)

if !dir.IsDir() {
    fmt.Println(chalk.Red, "Erreur : Le chemin spécifié n'est pas un dossier")
    os.Exit(0)
}

if errors.Is(err, os.ErrNotExist) {
    fmt.Println(chalk.Red, "Erreur : Dossier introuvable")
    os.Exit(0)
}


screen.Clear()
screen.MoveTopLeft()
fmt.Println(chalk.Green, "Dossier de téléchargement par défaut changé avec succès")

错误信息

le chemin est :  '/Users/eliezayat/Downloads/bassine wavy.png'
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x18 pc=0x119b260]

goroutine 1 [running]:
freetranscli/cmd.glob..func3(0x1370900?, {0x11ef012?, 0x0?, 0x0?})
        /Users/eliezayat/Documents/freetranscli/cmd/set.go:44 +0x280
github.com/spf13/cobra.(*Command).execute(0x1370900, {0x13a3d80, 0x0, 0x0})
        /Users/eliezayat/go/pkg/mod/github.com/spf13/cobra@v1.6.1/command.go:920 +0x847
github.com/spf13/cobra.(*Command).ExecuteC(0x1370620)
        /Users/eliezayat/go/pkg/mod/github.com/spf13/cobra@v1.6.1/command.go:1044 +0x3bd
github.com/spf13/cobra.(*Command).Execute(...)
        /Users/eliezayat/go/pkg/mod/github.com/spf13/cobra@v1.6.1/command.go:968
freetranscli/cmd.Execute()
        /Users/eliezayat/Documents/freetranscli/cmd/root.go:28 +0x25
main.main()
        /Users/eliezayat/Documents/freetranscli/main.go:8 +0x17
exit status 2

问题根源

错误核心是空指针解引用:当输入路径指向文件而非文件夹时,os.Stat虽不会返回错误,但代码未先处理os.Stat可能的错误(比如路径不存在时err非空,此时dir为nil),就直接调用dir.IsDir(),导致nil指针调用方法触发Panic。

修复方案

调整代码逻辑,先处理错误,再检查路径类型,同时补充写入权限检查:

var dldpath string
inquire.Query().Input(&dldpath, "Chemin du dossier de téléchargement ", nil).Exec()

println("le chemin est : ", dldpath)

if len(dldpath) == 0 {
    fmt.Println(chalk.Red, "Erreur : Vous devez spécifier un dossier à téléverser")
    os.Exit(0)
}

// 先处理os.Stat的错误
dir, err := os.Stat(dldpath)
if err != nil {
    if errors.Is(err, os.ErrNotExist) {
        fmt.Println(chalk.Red, "Erreur : Dossier introuvable")
    } else {
        fmt.Println(chalk.Red, "Erreur lors de la vérification du chemin :", err)
    }
    os.Exit(0)
}

// 检查是否为文件夹
if !dir.IsDir() {
    fmt.Println(chalk.Red, "Erreur : Le chemin spécifié n'est pas un dossier")
    os.Exit(0)
}

// 检查写入权限:尝试创建临时文件验证
tempFile, err := os.CreateTemp(dldpath, "test-write-")
if err != nil {
    fmt.Println(chalk.Red, "Erreur : Aucun droit d'écriture sur le dossier")
    os.Exit(0)
}
// 清理临时文件
os.Remove(tempFile.Name())

screen.Clear()
screen.MoveTopLeft()
fmt.Println(chalk.Green, "Dossier de téléchargement par défaut changé avec succès")

修复要点

  1. 错误优先处理:调用os.Stat后先判断err,避免dir为nil时调用方法
  2. 路径类型校验:确认dir非空后,再检查是否为文件夹
  3. 写入权限验证:通过创建临时文件的方式,实际验证文件夹的写入权限(比单纯检查文件模式更可靠)

内容的提问来源于stack exchange,提问作者Elie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.12 09:45:34