go变量声明即约束类型,未初始化会报错;var需指定类型或初始值,:=仅限函数内且须有新变量;所有变量有确定零值,非nil;作用域由声明位置决定,无变量提升。

Go 里变量声明不是“先定义再赋值”,而是“声明即约束类型”,不初始化就用会直接报错。
var 声明变量时为什么必须指定类型或给初始值
Go 是静态类型语言,编译期就要确定每个变量的内存布局。var 单独声明不赋值时,必须写明类型,否则编译器无法推导:
-
var age int✅ 合法,类型明确 -
var name❌ 编译错误:missing type in variable declaration -
var count = 42✅ 合法,从字面量推导出int
常见踩坑:在函数外(包级)用 var 声明未初始化变量却漏写类型,导致编译失败;而函数内可以用 := 省略类型,但仅限于短变量声明且必须在新变量首次出现时使用。
:= 只能在函数内部用,且不能重复声明同名变量
:= 是短变量声明,本质是 var + 类型推导 + 初始化三合一,但它有严格限制:
- 只能出现在函数体内,包级作用域禁止使用
:= - 左边至少有一个新变量名,否则报错:
no new variables on left side of := - 不能对已声明的变量(哪怕在其他作用域)复用
:=覆盖,比如err := foo()后再写err := bar()就会失败
示例场景:循环中开 goroutine 闭包捕获变量,误用 := 可能导致所有 goroutine 共享同一个 i 的地址——这不是语法问题,而是逻辑陷阱,得靠显式传参或复制值来避免。
零值不是 nil,不同类型零值不同
Go 没有“未初始化”概念,所有变量声明后立刻有确定的零值,但零值 ≠ nil,也≠空字符串或 0 的语义安全默认:
-
int零值是0,string是"",bool是false - 指针、slice、map、channel、func、interface 的零值才是
nil - 结构体变量的零值是各字段零值的组合,不是
nil(结构体本身不能为nil)
容易忽略的点:判断 map 是否为空,不能只看是否为 nil,还要用 len(m) == 0;而向 nil map 写入会 panic,必须先 make。
变量作用域和生命周期由声明位置决定,不是大括号“看起来像”就生效
Go 的作用域规则很实在:变量在哪一级代码块里声明,就只在那一级及嵌套内可见。但有几个硬约束:
- if/for/switch 语句里的
:=声明,变量只在该语句块内有效,外面访问不到 - 包级
var声明的变量,首字母大写才对外可见;小写就是包私有 - 没有“变量提升”(hoisting),不能在声明前使用,哪怕在同一作用域
典型错误:在 if err != nil { return } 后面直接用 := 声明变量,结果因为前面 if 块里已经声明过同名变量,导致编译失败或逻辑错乱。
变量能不能用、怎么用、为什么报错,全看声明那一刻的位置、方式和上下文。类型、作用域、零值这三件事没理清,后面所有引用、传参、并发都容易埋雷。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











