Go变量声明严格遵循作用域与类型规则:包级变量必须用var,函数内可用:=但需有新变量;未使用变量编译失败;零值存在但nil map/slice操作需初始化;类型推导可能引发跨平台问题。

Go 语言变量声明不是“怎么方便怎么来”,而是“不按规则就编译失败”。var 和 := 不是风格偏好,是作用域、类型安全和编译约束的硬性分界。
包级变量必须用 var,不能用 :=
在函数外(即包作用域)写 s := "hello",编译器直接报错:syntax error: non-declaration statement outside function body。这不是警告,是语法错误。
-
var是唯一合法方式,例如:var port = 8080或var timeout int = 30 - 批量声明更清晰:
var (dbHost string = "localhost" dbPort int = 5432) - 包级变量若未赋值,必须显式写类型:
var configPath string—— 写成var configPath会报missing type in variable declaration
:= 只能在函数内用,且左边至少有一个新变量
:= 看似是赋值,实则是“带类型推导的声明”。它不是覆盖,是声明——所以重复使用会触发 no new variables on left side of :=。
- 合法:
err := foo()(首次声明err),接着err, data := bar()(data是新变量,允许) - 非法:
err := foo()后再写err := bar()(无新变量,报错) - 常见陷阱:循环中
for i := range items { go func() { fmt.Println(i) }() }—— 所有 goroutine 共享同一个i地址,不是:=的错,但用:=声明临时变量(如idx := i)能快速规避
未使用的变量会导致编译失败
Go 不允许“先声明后考虑怎么用”。哪怕只是 var debug bool 没被读写,编译就报 declared and not used。
立即学习“go语言免费学习笔记(深入)”;
- 调试时注释掉某行?记得顺手删掉对应变量,或用
_匿名接收:_ = someValue - 从函数返回多个值但只关心一个?用
_, err := doSomething()显式丢弃 - 结构体字段未用?不影响;但局部变量未用,一定报错 —— 这是 Go 强制你清理冗余逻辑的机制,不是 bug
零值不是 nil,但没初始化就用会 panic
所有变量声明即有零值:int 是 0,string 是 "",map 是 nil。但 nil map 不能直接写,nil slice 可以读长度但不能取下标。
-
var m map[string]int→m是nil,m["k"] = 1会 panic - 正确做法:
m := make(map[string]int)或var m = make(map[string]int - 切片同理:
var s []int合法,len(s)返回0,但s[0]panic;需s := make([]int, 0)或字面量s := []int{}
最易忽略的是作用域和类型推导的耦合:同一行 a, b := 1, "x" 中 a 推导为 int,但在 32 位环境可能被当作 int32,对接 C 函数或反射时出问题。这时候宁可用 var a int = 1 显式锁死类型。


















