短变量声明 := 只能在函数内部使用,包级作用域必须用 var 或 const;:= 是声明并初始化,要求左侧至少有一个新变量,否则报“no new variables”错误。

短变量声明 := 只能在函数内部用
Go 不允许在包级别(即函数外)使用 :=,否则会报错 syntax error: non-declaration statement outside function body。这是初学者最常踩的坑——想在全局写 config := loadConfig(),结果编译直接失败。
正确做法是:全局变量必须显式用 var 声明,或用 const;:= 仅限函数体内,且左侧变量名必须全部为新声明(至少有一个是新变量)。
- ✅ 合法:
name := "Alice"、age, city := 30, "Beijing" - ❌ 非法:
var name string; name := "Alice"(重复声明) - ⚠️ 注意:
if x := getVal(); x > 0 { ... }中的x作用域仅限该if块内
:= 会自动推导类型,但不能用于已有变量重新赋值
它不是“赋值操作符”,而是“声明并赋值”。如果左侧出现已声明的变量(在同一作用域),且没有其他新变量,就会触发错误 no new variables on left side of :=。
比如你写了两次 err := doSomething(),第二次就会报错——哪怕第一次的 err 是在 if 里声明的,只要当前作用域已存在同名变量,就不能再用 :=。
- ✅ 正确(引入新变量):
result, err := process() - ✅ 正确(复用旧变量 + 新变量):
err, msg := parse()(前提是msg是新的) - ❌ 错误(仅复用):
err := parse()(若err已存在)→ 改用err = parse()
和 var 比,:= 更紧凑,但牺牲了显式类型控制
当你需要明确类型(比如避免 int 和 int64 混淆)、或初始化值为零值(如空切片 []string{})时,var 更稳妥。而 := 在快速构建局部逻辑时更顺手。
典型场景:HTTP 处理器里一连串带 err 的调用,用 := 能让错误处理链更干净:
func handler(w http.ResponseWriter, r *http.Request) {
id := r.URL.Query().Get("id")
user, err := db.FindUser(id)
if err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
data, err := json.Marshal(user) // 这里 err 是新变量,没问题
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
w.Write(data)
}
但如果某步返回的是 int,而你需要传给只接受 int64 的函数,:= 推导出的类型可能不匹配,这时就得回退到 var n int64 = getInt()。
嵌套作用域中用 := 容易意外遮蔽外层变量
Go 允许内层作用域用同名变量“遮蔽”(shadow)外层变量,比如 for 循环里写 i := 0,会创建一个新 i,而不是修改外层的。调试时容易误以为是同一个变量。
这种遮蔽本身合法,但会导致难以察觉的 bug,尤其在闭包捕获循环变量时:
:=
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











