1. 引言
Go 语言的变量与常量看似简单,但其中暗藏不少容易踩坑的细节。本篇围绕三种声明方式、iota 枚举、作用域规则与零值机制,帮你快速掌握惯用写法,避开常见的变量遮蔽陷阱。
2. 三种声明方式
Go 中声明变量主要有三种方式:var、:=和const。
2.1 var 声明
var是最基础的声明方式,适用于包级变量、需要显式类型或先声明后赋值的场景。
varnamestring="Go"varcountint// 零值初始化vara,bint=1,22.2 短变量声明 :=
:=是函数内最常用的声明方式,由编译器推断类型,简洁高效。
funcmain(){name:="Go"count:=42}2.3 const 常量
const用于声明不可修改的常量,支持多种类型,且可在编译期计算。
constPi=3.14159constMaxSize=10243. 短变量声明 := 的限制
:=虽然方便,但有以下限制:
- 只能在函数内使用:包级变量不能用
:=,必须用var。 - 左侧至少有一个新变量:如果左侧变量都已存在,则必须用
=赋值。
x:=1x,y:=2,3// 合法:y 是新变量x=4// 合法:x 已存在,用 =4. 常量与 iota 枚举
iota是 Go 中用于常量递增的预定义标识符,在const块中从 0 开始逐行递增。
const(A=iota// 0B// 1C// 2)iota也支持跳过和表达式运算:
const(_=iota// 跳过 0KB=1<<(10*iota)// 1 << 10 = 1024MB// 1 << 20GB// 1 << 30)5. 作用域规则
Go 的作用域分为包级、函数级和块级,遵循就近匹配原则。
5.1 包级、函数级与块级
packagemainvarglobal="包级变量"// 包级作用域funcmain(){local:="函数级变量"// 函数级作用域iftrue{inner:="块级变量"// 块级作用域fmt.Println(inner)}}5.2 变量遮蔽(Shadowing)
变量遮蔽是 Go 中最常见的陷阱之一:在内部作用域用:=声明同名变量,会创建新变量而非赋值。
x:=1iftrue{x:=2// 这是新变量,不是赋值fmt.Println(x)// 2}fmt.Println(x)// 16. 零值机制
Go 中没有「未初始化」的变量。声明后未赋值的变量会自动获得对应类型的零值:
- 数值类型:
0 - 布尔类型:
false - 字符串:
"" - 指针、切片、map、函数等:
nil
varnumint// 0varflagbool// falsevarsstring// ""varp*int// nil7. 易错点与常见误解
:=在 if/for/switch 中创建新作用域导致变量遮蔽:注意内部同名变量是新变量。- 常量不能用
:=声明:常量必须用const。 - 包级变量不能用
:=:包级只能使用var或const。 - 未使用的局部变量会导致编译错误:但包级变量不会。
funcmain(){unused:=1// 编译错误:unused declared and not used}8. 总结
掌握var、:=、const的适用场景,理解iota的递增规则,认清作用域与零值机制,是写出规范 Go 代码的基础。尤其要警惕:=在嵌套作用域中造成的变量遮蔽,这是面试和日常开发中最高频的易错点之一。