Go语言提供了两种核心的变量声明方式,分别是var关键字声明和短变量声明:=,两者在语法规则、作用域限制和初始化要求上存在明显差异,尤其是在顶层作用域和块级作用域下的表现完全不同。

var关键字声明规则
var是Go语言官方的变量声明关键字,支持在任意作用域下使用,语法形式比较灵活。
基本语法格式
var声明可以显式指定变量类型,也可以让编译器自动推导类型,还可以同时声明多个变量:
// 显式指定类型并初始化
var name string = "test"
// 显式指定类型不初始化,会使用零值
var age int
// 自动推导类型
var score = 95.5
// 批量声明多个变量
var (
a int
b string
c bool
)
作用域表现
var可以在顶层作用域(包级作用域)和块级作用域(函数、if、for等代码块内部)使用:
- 顶层作用域声明的
var变量属于包级变量,整个包内都可以访问,首字母大写时还可以被其他包导入访问。 - 块级作用域声明的
var变量仅在当前代码块内有效,不会覆盖外层同名的var变量,而是形成局部隐藏。
短变量声明:=规则
:=是Go的短变量声明语法,仅能在块级作用域下使用,不支持顶层作用域声明。
基本语法格式
:=左侧是变量名,右侧是初始值,变量类型由编译器自动推导,必须同时完成初始化:
// 单个变量短声明
count := 10
// 多个变量短声明
x, y := 20, "hello"
// if代码块内短声明
if num := 5; num > 3 {
fmt.Println(num)
}
作用域限制
:=只能在函数、方法、if、for、switch等块级作用域中使用,在包顶层使用会直接编译报错:
// 以下代码在包顶层会编译错误
// errMsg := "error" // 不允许
func main() {
// 函数内部使用正常
errMsg := "error"
fmt.Println(errMsg)
}
顶层与块级作用域的核心差异
| 对比项 | var声明 | :=声明 |
|---|---|---|
| 顶层作用域可用性 | 支持 | 不支持 |
| 块级作用域可用性 | 支持 | 支持 |
| 初始化要求 | 可初始化可不初始化 | 必须初始化 |
| 类型指定 | 可指定可推导 | 仅支持推导 |
| 变量覆盖特性 | 块内声明不直接覆盖外层,形成局部隐藏 | 块内声明会覆盖外层同名变量 |
常见使用误区示例
很多开发者会在块级作用域误用var导致变量覆盖不符合预期,或者错误在顶层使用:=:
package main
import "fmt"
var a int = 10 // 顶层var声明
func main() {
// 块内用var声明同名变量,不会修改外层的a
var a int = 20
fmt.Println(a) // 输出20,局部隐藏
// 块内用:=声明同名变量,覆盖外层a
a := 30
fmt.Println(a) // 输出30
// 错误示例:在if块外使用:=会报错
// b := 5 // 这里如果不在块内,实际是函数块,但是如果是包顶层就会报错
}
// 以下代码编译报错,顶层不能用:=
// c := 100
在块级作用域中,如果左侧变量已经有外层同名变量,:=会优先视为对新变量的声明,而非给外层变量赋值,这一点需要特别注意,避免逻辑错误。