包级变量必须用var声明,不可用:=;函数内优先用:=但需满足至少一个新变量,显式类型必要时必须用var,未使用的局部变量无论var或:=均会编译失败。

包级变量必须用 var,不能用 :=
Go 不允许在函数外使用 :=。试图写 globalVar := "hello" 会直接编译失败,报错信息类似 syntax error: non-declaration statement outside function body。
包级变量(即全局变量)只能用 var 声明,支持三种写法:
-
var name string—— 只声明,零值初始化("") -
var count = 42—— 类型由值推导(int) -
var ( port int = 8080 host = "localhost" )—— 因式分解,适合批量声明
这类变量常用于配置、状态标志或共享资源,比如 var debugMode = true 或 var db *sql.DB。用 var 能明确表达“这是整个包可见的持久状态”,避免误以为是临时局部值。
函数内优先用 :=,但要注意“至少一个新变量”规则
在 func 内部,:= 是最自然的选择:简洁、类型自动推导、符合 Go 的惯用写法。
立即学习“go语言免费学习笔记(深入)”;
但它有个关键限制:左侧必须至少有一个新变量名,否则编译报错 no new variables on left side of :=。常见踩坑场景:
-
err := doSomething()后再写err := tryAgain()→ 错误(err已存在) - 正确写法是
err = tryAgain()(纯赋值),或err, data := tryAgain()(引入新变量data) - 循环中反复用
:=声明同名变量,实际每次都是新变量(作用域不同),但容易引发逻辑混淆
建议:单次声明用 :=;重复赋值或需复用已有变量时,改用 =。
显式类型有必要时一定用 var,别依赖推导
类型推导不是万能的。以下情况用 var 显式指定类型更安全:
- 需要特定整数宽度:
var id uint32 = 1001(id := 1001推导为int,可能与 API 签名不匹配) - 初始化为
nil的引用类型:var m map[string]int(m := make(map[string]int)是初始化,var才是真正声明未初始化的nil map) - 接口变量需绑定具体实现:
var w io.Writer = os.Stdout(w := os.Stdout推导为*os.File,失去接口抽象性)
这些地方硬写 := 会导致类型不符合预期,轻则编译失败,重则运行时 panic(如对 nil map 直接 range)。
局部变量未使用会编译失败,var 和 := 都一样
Go 强制要求:函数内声明的局部变量必须被读取或写入,否则报错 declared and not used。
这意味着:
-
name := "alice"之后没用到name→ 编译失败 -
var age int声明后没读/写 → 同样失败 - 调试时临时加变量,记得删掉或打上注释(如
_ = age)
这个规则和声明方式无关,但新手常误以为 := 更“宽松”。实际上,它只是语法糖,底层约束完全一致。
最容易被忽略的是多变量声明中的“部分未使用”——比如 a, b := getValue(),只用了 a 没用 b,就得用 a, _ := getValue() 显式丢弃。


















