Go 1.25.1 内置轻量代码静态检查工具,零依赖、开箱即用,精准揪出编译器看不见的隐藏Bug!
✨ 一、先搞懂:go vet 到底是什么?
go vet 是 Go 官方自带的代码诊断工具
不编译、不运行,只做静态扫描
专治:隐形Bug、语法不规范、并发误用、内存泄漏等坑
开发必用,提升代码质量超省心~
🚀 二、超简单使用命令(直接复制跑)
# 检查单个文件
go vet main.go
# 检查当前包
go vet .
# 递归检查整个项目(最常用!)
go vet ./...
# 查看所有检查规则
go tool vet help常用参数速查表
| 参数 | 作用 |
|---|---|
-shadow=true | 开启变量遮蔽检查 |
-atomic | 检查原子操作误用 |
-c=2 | 显示错误上下文代码 |
-json | 输出JSON格式检查结果 |
🧪 三、全覆盖Demo + 报错 + 修复(本地可直接跑)
所有代码统一用 go_vet.go,复制即可运行检查!
1️⃣ Printf 格式不匹配(高频错误)
错误代码
package main
import "fmt"
func main() {
// 格式符和类型不匹配
fmt.Printf("编号:%d\n", "golang")
fmt.Printf("姓名:%s\n", 100)
}检查命令
go vet go_vet.go报错
.\go_vet.go:7:23: fmt.Printf format %d has arg "golang" of wrong type string
.\go_vet.go:8:23: fmt.Printf format %s has arg 100 of wrong type int修复
fmt.Printf("编号:%s\n", "golang")
fmt.Printf("姓名:%d\n", 100)2️⃣ 变量遮蔽 Shadow(隐形逻辑坑)
Go 1.25+ 必须用官方工具:shadowcheck
go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow@latest错误代码
package main
import "fmt"
func main() {
err := fmt.Errorf("外层错误")
if true {
// 同名变量覆盖外层!
err := fmt.Errorf("内层错误")
fmt.Println(err)
}
// 拿到的还是外层变量
fmt.Println("最终错误:", err)
}检查命令
shadow go_vet.go报错
declaration of "err" shadows declaration at line 6修复
innerErr := fmt.Errorf("内层错误")3️⃣ atomic 原子操作误用(并发必崩)
错误代码
package main
import "sync/atomic"
func main() {
var num int
// 类型不匹配
atomic.AddInt64(&num, 1)
}检查命令
go vet -atomic go_vet.go报错
cannot use &num (value of type *int) as *int64 value in argument to atomic.AddInt64修复
var num int64
atomic.AddInt64(&num, 1)4️⃣ WaitGroup 误用(协程提前退出)
错误代码
package main
import (
"fmt"
"sync"
)
func main() {
var wg sync.WaitGroup
for i := 0; i < 2; i++ {
go func() {
wg.Add(1) // 错误:写在协程内部
fmt.Println("运行中")
wg.Done()
}()
}
wg.Wait()
}报错
WaitGroup.Add called from inside new goroutine修复
wg.Add(1)
go func(){
// ...
}()5️⃣ 网络地址拼接错误(不支持IPv6,实际官方不再检查)
错误代码
package main
import "fmt"
func main() {
host := "::1"
port := 8080
// 错误拼接
addr := fmt.Sprintf("%s:%d", host, port)
fmt.Println(addr)
}运行下面的命令都不报错。官方现在不提供内置检查,只能靠:
- 1. 人工规范
- 2. 必须使用 net.JoinHostPort(这是唯一安全写法)
- 3. 不再依赖 go vet 提醒
go vet go_vet.go
go vet -hostport go_vet.go
go tool vet go_vet.go结果:完全无警告 ✅
因为这个检查已经不存在了。
推荐的正确代码
import "net"
addr := net.JoinHostPort(host, fmt.Sprint(port))6️⃣ Context 泄漏(内存泄漏元凶)
错误代码
package main
import (
"context"
"time"
)
func main() {
// 丢弃 cancel 函数
ctx, _ := context.WithTimeout(context.Background(), 3*time.Second)
_ = ctx
}报错
the cancel function returned by context.WithTimeout should be called, not discarded, to avoid a context leak修复
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel()
_ = ctx7️⃣ 结构体标签错误(序列化失效)
错误代码
package main
import "encoding/json"
type User2 struct {
Name string `json:"name,"` // 多逗号
Age int `json:"age` // 少引号
}
func main() {
u := User2{"小红", 18}
json.Marshal(u)
}报错
struct field tag `json:"age` not compatible with reflect.StructTag.Get: bad syntax for struct tag value修复
Name string `json:"name"`
Age int `json:"age"`💡 四、开发必看最佳实践
- 1. 提交代码前必跑:
go vet ./... - 2. CI/CD 必须集成,不通过不让合并
- 3. 协程代码 必开
-atomic检查 - 4. 复杂逻辑 必开 安装和使用
shadow - 5. IDE 开启实时 vet 检查,提前避坑
⚠️ 五、新手误区澄清
❌ vet 报错 = 代码不能跑?
✅ 不是!是警告+隐患,必须修复高风险问题
❌ 只用在开发阶段?
✅ 必须全流程使用,保障线上质量
❌ 能替代单元测试?
✅ 不能!静态检查 + 单元测试 = 高质量代码
📌 总结
go vet 是 Go 开发者最轻量化、零成本、高回报的代码质量工具
7大高频错误全覆盖,本地复制Demo即可练习
养成检查习惯,Bug少一半,上线更安心~
MiaoAll