Skip to content

Go 基本语法:变量、常量、流程控制、函数

这一篇是 Go 入门阶段最关键的语法打底文。目标很明确:

  • 能写出结构清晰、可运行的 Go 代码
  • 知道什么时候用变量,什么时候用常量
  • 掌握常见流程控制写法(ifforswitch
  • 能定义并调用函数,理解多返回值与错误处理风格

如果你刚接触 Go,不用追求一次记全。建议边看边敲,先跑起来,再回头优化代码风格。


1. 变量

变量用于保存会变化的数据。Go 是静态类型语言,变量有明确类型,但在很多场景下可以由编译器自动推断。

1.1 声明方式

Go 中最常见的三种变量声明方式:

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
  • boolfalse
  • string""
  • 指针、切片、map、函数、接口:nil (对象类型的零值)
go
package main

import "fmt"

func main() {
 var n int
 var ok bool
 var s string
 fmt.Println(n, ok, s) // 0 false ""
}

1.3 一次声明多个变量

go
var a, b, c int = 1, 2, 3

var (
 username = "alice"
 score    = 100
 active   = true
)

当变量较多时,使用 var (...)const(...) 分组声明更清晰。

1.4 匿名变量与重新赋值

Go 支持使用 _ 丢弃不需要的值,这在多返回值函数中非常常见。

go
value, _ := div(10, 3)
fmt.Println(value)

另外要注意::= 不是“普通赋值”,它要求左侧至少有一个新变量。

go
x := 10
x = 20   // 普通赋值
// x := 30 // 编译错误:没有新变量

2. 常量

常量用于保存不会变化的值,使用 const 声明。

go
const Pi = 3.1415926
const AppName string = "demo-go"

2.1 常量分组

go
const (
 StatusOK    = 200
 StatusError = 500
)

2.2 iota:常量计数器

iota 常用于定义一组有规律递增的常量(状态码、枚举值、位标记等)。

go
const (
 Sunday = iota // 0
 Monday        // 1
 Tuesday       // 2
)

iota 在每个 const 块中从 0 开始,每新增一行自动加 1

位运算场景:

go
const (
 Read = 1 << iota  // 1  (001)
 Write             // 2  (010)
 Execute           // 4  (100)
)

这类写法在权限控制中很常见。


3. 流程控制

Go 的流程控制语法不复杂,但风格很统一。

3.1 if

go
if score >= 90 {
 fmt.Println("A")
} else if score >= 60 {
 fmt.Println("B")
} else {
 fmt.Println("C")
}

Go 支持在 if 前写一条短语句,作用域仅在当前 if/else 中:

go
if n := len("golang"); n > 3 {
 fmt.Println("长度大于3", n)
}

3.2 for

Go 只有 for,但能覆盖其他语言里的 whiledo while 使用场景。

  1. 经典三段式:
go
for i := 0; i < 5; i++ {
 fmt.Println(i)
}
  1. while
go
sum := 0
for sum < 10 {
 sum++
}
fmt.Println(sum)
  1. 无限循环:
go
for {
 // 通常配合 break / return
 break
}
  1. 遍历(range):
go
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)。

go
day := 2
switch day {
case 1:
 fmt.Println("Mon")
case 2:
 fmt.Println("Tue")
default:
 fmt.Println("Unknown")
}

也可以不写表达式,写成条件分支:

go
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 breakcontinue

  • break:跳出当前循环或 switch
  • continue:跳过本轮循环,进入下一轮
go
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 函数定义

go
func add(a int, b int) int {
 return a + b
}

同类型参数可简写:

go
func add(a, b int) int {
 return a + b
}

4.2 多返回值

Go 支持多个返回值,这让错误处理风格更加自然。

go
func div(a, b int) (int, error) {
 if b == 0 {
 return 0, fmt.Errorf("除数不能为0")
 }
 return a / b, nil
}

调用:

go
result, err := div(10, 2)
if err != nil {
 fmt.Println("计算失败:", err)
 return
}
fmt.Println("结果:", result)

4.3 命名返回值

go
func rectangle(width, height int) (area int, perimeter int) {
 area = width * height
 perimeter = 2 * (width + height)
 return
}

命名返回值在简单函数里可读性还可以,但不要滥用。函数一复杂,直接显式返回通常更清晰。

4.4 可变参数

go
func sum(nums ...int) int {
 total := 0
 for _, n := range nums {
 total += n
 }
 return total
}

调用:

go
fmt.Println(sum(1, 2, 3))

arr := []int{4, 5, 6}
fmt.Println(sum(arr...))

4.5 函数也是值

函数可以赋值给变量,也可以作为参数传递。

go
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. 综合示例

把前面四部分串起来,写一个可直接运行的小程序:

go
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. 常见坑与建议

  1. 不要把 := 用在包级作用域。
  2. 注意区分“声明”与“赋值”,避免 no new variables on left side of :=
  3. switch 默认不会贯穿,不要按 C/Java 的习惯想当然。
  4. Go 没有 while 关键字,统一使用 for
  5. 优先使用“多返回值 + error”处理错误,而不是直接 panic

7. 小结

你现在应该已经具备这些能力:

  • 会使用 var:= 声明变量,理解零值和作用域
  • 会用 constiota 管理常量
  • 会写 ifforswitch 组织流程
  • 会定义函数、处理多返回值、编写可变参数函数

下一篇将进入数据结构基础:数组、切片、map、字符串,以及它们在内存与性能上的关键差异。

上次更新于: