filepath.Base提取路径末段文件名(如/main.go→main.go),再用filepath.Ext获取扩展名,最后用strings.TrimSuffix安全去除;Go 1.20+可用strings.CutSuffix替代,返回布尔值明确标识是否成功去除。

用 filepath.Base 提取纯文件名(含扩展)
从完整路径中拿“最后一段”是第一步,比如 /home/user/app/main.go → main.go。这步必须用 filepath.Base,不是 path.Base —— 后者不处理 Windows 路径分隔符 \,跨平台会出错。
常见错误是直接对原始路径用 strings.Split 或正则切分,结果在 C:\Program Files\app.exe 或 ./bin/my.tool 上崩掉。
-
filepath.Base自动识别/和\,返回末尾非空段 - 若输入是空字符串或全路径分隔符(如
///),它返回.,需额外判断 - 它不碰扩展名,
archive.tar.gz仍原样返回
用 filepath.Ext + strings.TrimSuffix 去掉扩展名
filepath.Ext 是唯一可靠提取扩展名的方式:它只认最后一个点之后、且该点不在开头的部分。所以 .gitignore → "",Makefile → "",config.yaml.bak → .bak,image.tar.gz → .gz。
strings.TrimSuffix 在扩展名为空时无副作用,安全可叠加:
立即学习“go语言免费学习笔记(深入)”;
name := filepath.Base(path) ext := filepath.Ext(name) basename := strings.TrimSuffix(name, ext)
- 不要用
strings.Split(name, ".")取第一个元素——test.conf.d会被错切成test - 避免手写
strings.LastIndex+ 切片,容易漏掉.noext这类边界情况 - Windows 下可执行文件可能带
.exe,filepath.Ext能正确捕获
Go 1.20+ 可用 strings.CutSuffix 替代 TrimSuffix
如果项目已升级到 Go 1.20 或更高版本,strings.CutSuffix 比 TrimSuffix 多一个布尔返回值,能明确知道扩展名是否真实存在:
name := filepath.Base(path)
ext := filepath.Ext(name)
if basename, ok := strings.CutSuffix(name, ext); ok {
// 确实去掉了扩展名
} else {
// ext 是空字符串,name 本就不含扩展
}
-
CutSuffix不改变逻辑,但帮你省一次filepath.Ext(name) != ""判断 - 低版本 Go(
- 它和
TrimSuffix底层实现一致,性能无差异
注意 os.Args[0] 的特殊性:它不是源文件名
想获取当前运行程序的命令名(如用户敲的 ./server 或 mytool),得处理 os.Args[0],但它不是源码文件名:
-
go run main.go时,os.Args[0]是临时二进制路径(如/tmp/go-buildxxx/a.out),跟main.go无关 -
go build -o myapp . && ./myapp时,os.Args[0]才是./myapp,经filepath.Base+TrimSuffix后得myapp - 别试图从二进制里反推
main.go—— 编译后源码信息已丢失,标准库无此能力
真正容易被忽略的是:当程序被 symlink 启动时,os.Args[0] 是 symlink 路径,不是真实目标路径;需要 filepath.EvalSymlinks 预处理才能拿到最终可执行文件名。


















