Go 基本语法:变量、常量、流程控制、函数
这一篇是 Go 入门阶段最关键的语法打底文。目标很明确:
- 能写出结构清晰、可运行的 Go 代码
- 知道什么时候用变量,什么时候用常量
- 掌握常见流程控制写法(
if、for、switch) - 能定义并调用函数,理解多返回值与错误处理风格
如果你刚接触 Go,不用追求一次记全。建议边看边敲,先跑起来,再回头优化代码风格。
1. 变量
变量用于保存会变化的数据。Go 是静态类型语言,变量有明确类型,但在很多场景下可以由编译器自动推断。
1.1 声明方式
Go 中最常见的三种变量声明方式:
package main
import "fmt"
func main() {
// 方式1:完整声明(显式类型)
var age int = 20
// 方式2:类型推断
var name = "Tom"
// 方式3:短变量声明(只能在函数内部使用)
city := "Shanghai"
fmt.Println(age, name, city)
}要点:
var可以在函数内外使用。:=只能在函数内部使用,不能用于包级变量。- 未显式赋值的变量会有零值。
1.2 零值(Zero Value)
Go 不允许使用未初始化的局部变量,但会自动赋零值:
- 数值类型:
0 bool:falsestring:""- 指针、切片、map、函数、接口:
nil(对象类型的零值)
package main
import "fmt"
func main() {
var n int
var ok bool
var s string
fmt.Println(n, ok, s) // 0 false ""
}1.3 一次声明多个变量
var a, b, c int = 1, 2, 3
var (
username = "alice"
score = 100
active = true
)当变量较多时,使用 var (...) 或 const(...) 分组声明更清晰。
1.4 匿名变量与重新赋值
Go 支持使用 _ 丢弃不需要的值,这在多返回值函数中非常常见。
value, _ := div(10, 3)
fmt.Println(value)另外要注意::= 不是“普通赋值”,它要求左侧至少有一个新变量。
x := 10
x = 20 // 普通赋值
// x := 30 // 编译错误:没有新变量2. 常量
常量用于保存不会变化的值,使用 const 声明。
const Pi = 3.1415926
const AppName string = "demo-go"2.1 常量分组
const (
StatusOK = 200
StatusError = 500
)2.2 iota:常量计数器
iota 常用于定义一组有规律递增的常量(状态码、枚举值、位标记等)。
const (
Sunday = iota // 0
Monday // 1
Tuesday // 2
)iota 在每个 const 块中从 0 开始,每新增一行自动加 1。
位运算场景:
const (
Read = 1 << iota // 1 (001)
Write // 2 (010)
Execute // 4 (100)
)这类写法在权限控制中很常见。
3. 流程控制
Go 的流程控制语法不复杂,但风格很统一。
3.1 if
if score >= 90 {
fmt.Println("A")
} else if score >= 60 {
fmt.Println("B")
} else {
fmt.Println("C")
}Go 支持在 if 前写一条短语句,作用域仅在当前 if/else 中:
if n := len("golang"); n > 3 {
fmt.Println("长度大于3", n)
}3.2 for
Go 只有 for,但能覆盖其他语言里的 while 与 do while 使用场景。
- 经典三段式:
for i := 0; i < 5; i++ {
fmt.Println(i)
}- 类
while:
sum := 0
for sum < 10 {
sum++
}
fmt.Println(sum)- 无限循环:
for {
// 通常配合 break / return
break
}- 遍历(
range):
nums := []int{10, 20, 30}
for index, value := range nums {
fmt.Println(index, value)
}
for _, value := range nums { // 不需要索引时用 _
fmt.Println(value)
}3.3 switch
Go 的 switch 默认不会向下贯穿(不会自动执行下一个 case)。
day := 2
switch day {
case 1:
fmt.Println("Mon")
case 2:
fmt.Println("Tue")
default:
fmt.Println("Unknown")
}也可以不写表达式,写成条件分支:
score := 85
switch {
case score >= 90:
fmt.Println("A")
case score >= 60:
fmt.Println("B")
default:
fmt.Println("C")
}如果你确实需要向下执行,可以显式使用 fallthrough,但应谨慎使用,避免代码可读性下降。 注意: fallthrough 的行为是无条件执行下一个 case 的代码块,而不会对下一个 case 的条件进行判断。
3.4 break、continue
break:跳出当前循环或switchcontinue:跳过本轮循环,进入下一轮
for i := 1; i <= 5; i++ {
if i == 3 {
continue
}
if i == 5 {
break
}
fmt.Println(i) // 输出 1 2 4
}4. 函数
函数是 Go 程序组织逻辑的核心。Go 的函数语法强调简洁和可读性。
4.1 函数定义
func add(a int, b int) int {
return a + b
}同类型参数可简写:
func add(a, b int) int {
return a + b
}4.2 多返回值
Go 支持多个返回值,这让错误处理风格更加自然。
func div(a, b int) (int, error) {
if b == 0 {
return 0, fmt.Errorf("除数不能为0")
}
return a / b, nil
}调用:
result, err := div(10, 2)
if err != nil {
fmt.Println("计算失败:", err)
return
}
fmt.Println("结果:", result)4.3 命名返回值
func rectangle(width, height int) (area int, perimeter int) {
area = width * height
perimeter = 2 * (width + height)
return
}命名返回值在简单函数里可读性还可以,但不要滥用。函数一复杂,直接显式返回通常更清晰。
4.4 可变参数
func sum(nums ...int) int {
total := 0
for _, n := range nums {
total += n
}
return total
}调用:
fmt.Println(sum(1, 2, 3))
arr := []int{4, 5, 6}
fmt.Println(sum(arr...))4.5 函数也是值
函数可以赋值给变量,也可以作为参数传递。
func apply(a, b int, op func(int, int) int) int {
return op(a, b)
}
func main() {
res := apply(3, 4, func(x, y int) int {
return x * y
})
fmt.Println(res) // 12
}5. 综合示例
把前面四部分串起来,写一个可直接运行的小程序:
package main
import "fmt"
const (
AppName = "Go Syntax Demo"
)
func grade(score int) string {
switch {
case score >= 90:
return "A"
case score >= 60:
return "B"
default:
return "C"
}
}
func average(nums ...int) float64 {
if len(nums) == 0 {
return 0
}
total := 0
for _, n := range nums {
total += n
}
return float64(total) / float64(len(nums))
}
func main() {
name := "Alice" // 变量
const passLine = 60 // 常量
scores := []int{88, 72, 95}
fmt.Println("应用:", AppName)
fmt.Println("用户:", name)
for i, s := range scores { // 流程控制
fmt.Printf("第%d门成绩: %d, 等级: %s\n", i+1, s, grade(s))
}
avg := average(scores...) // 函数
fmt.Printf("平均分: %.2f\n", avg)
if avg >= passLine {
fmt.Println("总体通过")
} else {
fmt.Println("总体未通过")
}
}6. 常见坑与建议
- 不要把
:=用在包级作用域。 - 注意区分“声明”与“赋值”,避免
no new variables on left side of :=。 switch默认不会贯穿,不要按 C/Java 的习惯想当然。- Go 没有
while关键字,统一使用for。 - 优先使用“多返回值 +
error”处理错误,而不是直接panic。
7. 小结
你现在应该已经具备这些能力:
- 会使用
var、:=声明变量,理解零值和作用域 - 会用
const与iota管理常量 - 会写
if、for、switch组织流程 - 会定义函数、处理多返回值、编写可变参数函数
下一篇将进入数据结构基础:数组、切片、map、字符串,以及它们在内存与性能上的关键差异。