Go 语言基础语法:从零开始掌握核心概念
如果你正在学习一门新编程语言,Go 语言(又称 Golang)是一个非常值得投入精力的选择。它由 Google 开发,以简洁、高效和并发能力强著称。无论你是初学者还是有一定经验的开发者,掌握 Go 语言基础语法,都是迈向实战的第一步。
Go 语言的设计哲学是“简单即美”。它没有复杂的继承体系,没有泛型(直到 Go 1.18 才引入),但它的语法清晰、类型安全、编译快速。这使得它特别适合构建微服务、命令行工具和高并发系统。
今天我们就来系统梳理 Go 语言基础语法中的关键部分。文章内容循序渐进,适合从零开始的开发者,也适合想巩固基础的中级开发者。
变量声明与数据类型
在任何编程语言中,变量都是存储数据的基本单元。Go 语言的变量声明方式非常直观。
package main
import "fmt"
func main() {
// 方式一:显式声明类型
var name string = "Alice"
var age int = 25
var isStudent bool = true
// 方式二:类型推断(推荐)
message := "Hello, Go!"
count := 100
pi := 3.14159
// 输出变量值
fmt.Println("姓名:", name)
fmt.Println("年龄:", age)
fmt.Println("是否学生:", isStudent)
fmt.Println("消息:", message)
fmt.Println("计数:", count)
fmt.Println("π 的近似值:", pi)
}
说明:
var是 Go 中用于声明变量的关键词。:=是 Go 的短变量声明语法,它会自动推断变量类型,非常方便。- 注意:
:=只能在函数内部使用,不能用于全局变量声明。- 声明变量后必须使用,否则编译会报错(Go 的严谨性体现之一)。
基本数据类型一览
| 类型 | 说明 | 示例 |
|---|---|---|
int |
整数类型,根据系统位数决定大小 | var n int = 42 |
int8 / int16 / int32 / int64 |
有符号整数,位数明确 | var b int8 = -128 |
uint / uint8 / uint16 / uint32 / uint64 |
无符号整数 | var u uint = 255 |
float32 / float64 |
浮点数,float64 更常用 |
var f float64 = 3.14 |
bool |
布尔类型,值为 true 或 false | var t bool = true |
string |
字符串类型,UTF-8 编码 | var s string = "Go" |
提示:Go 语言中字符串是不可变的,一旦创建就不能修改。如果需要拼接,可以使用
+操作符或strings.Builder。
控制流程:if、for、switch
控制流程是程序执行逻辑的核心。Go 语言的控制语句设计得非常简洁。
if 条件语句
package main
import "fmt"
func main() {
score := 85
// Go 的 if 语句支持初始化语句
if level := "未达标"; score < 60 {
fmt.Println("成绩:", score, ",等级:", level)
} else if score < 80 {
fmt.Println("成绩:", score, ",等级:B")
} else {
fmt.Println("成绩:", score, ",等级:A")
}
}
说明:
if后面可以跟一个初始化语句,作用域仅限于当前if块。- Go 不支持括号中的条件表达式,必须用大括号
{}包裹代码块。- 没有
else if的括号,直接写else if即可。
for 循环:唯一循环结构
Go 只有 for 一种循环,但它功能强大,可以替代其他语言的 while 和 for。
package main
import "fmt"
func main() {
// 传统 for 循环
for i := 0; i < 5; i++ {
fmt.Printf("第 %d 次循环\n", i+1)
}
// 类似 while 的循环
j := 0
for j < 3 {
fmt.Printf("while 循环:%d\n", j)
j++
}
// 无限循环(配合 break 使用)
k := 0
for {
fmt.Printf("无限循环:%d\n", k)
k++
if k >= 2 {
break // 退出循环
}
}
}
说明:
for的三个部分(初始化、条件、递增)是可选的,但分号必须保留。- 无限循环
for {}常用于服务启动,配合break或return退出。
switch 语句:多分支选择
package main
import "fmt"
func main() {
day := 3
switch day {
case 1:
fmt.Println("星期一")
case 2:
fmt.Println("星期二")
case 3:
fmt.Println("星期三")
default:
fmt.Println("其他日子")
}
}
说明:
- Go 的
switch不需要break,每个case自动结束。- 如果需要“穿透”执行,可以使用
fallthrough关键字。switch也可以用于类型判断,结合type switch使用。
函数定义与调用
函数是 Go 语言中组织代码的基本单元。它的语法清晰,参数和返回值定义明确。
package main
import "fmt"
// 定义一个函数:计算两个数的和
func add(a int, b int) int {
return a + b
}
// 带有命名返回值的函数
func divide(x, y float64) (result float64, err error) {
if y == 0 {
err = fmt.Errorf("除数不能为零")
return 0, err
}
result = x / y
return result, nil
}
func main() {
sum := add(10, 20)
fmt.Println("10 + 20 =", sum)
res, err := divide(10.0, 2.0)
if err != nil {
fmt.Println("错误:", err)
} else {
fmt.Println("10 / 2 =", res)
}
}
说明:
- 函数参数类型写在参数名后,多个参数可合并类型。
- 返回值可以命名,命名后可以直接使用
return返回。error是 Go 中处理错误的标准方式,函数返回error类型可判断是否出错。res, err := divide(...)是 Go 的“多值返回”特性,非常实用。
数组、切片与映射
创建数组与初始化
package main
import "fmt"
func main() {
// 定义一个长度为 5 的整型数组
var numbers [5]int
numbers[0] = 10
numbers[1] = 20
fmt.Println("数组:", numbers)
// 初始化数组
scores := [3]int{88, 92, 76}
fmt.Println("分数数组:", scores)
}
说明:
- 数组长度固定,不可变。
- 数组是值类型,赋值或传参时会复制整个数组。
- 通常在实际开发中更推荐使用切片。
切片(Slice):动态数组
package main
import "fmt"
func main() {
// 创建一个空切片
var slice []int
// 使用 make 创建切片
slice = make([]int, 3, 5) // 长度 3,容量 5
slice[0] = 100
slice[1] = 200
fmt.Println("切片内容:", slice)
// 从数组创建切片
data := [5]int{1, 2, 3, 4, 5}
subSlice := data[1:4] // 从索引 1 到 3(不包含 4)
fmt.Println("子切片:", subSlice)
// 切片追加元素
slice = append(slice, 300, 400)
fmt.Println("追加后:", slice)
}
说明:
- 切片是动态的,长度可变,内部维护一个底层数组。
make([]T, len, cap)用于创建指定长度和容量的切片。append会自动扩容,当容量不够时,会创建新数组并复制数据。
映射(Map):键值对容器
package main
import "fmt"
func main() {
// 创建一个映射,键为字符串,值为整数
studentScores := map[string]int{
"Alice": 95,
"Bob": 87,
"Charlie": 92,
}
// 查询值
score := studentScores["Alice"]
fmt.Println("Alice 的成绩:", score)
// 检查键是否存在
if value, exists := studentScores["Diana"]; exists {
fmt.Println("Diana 的成绩:", value)
} else {
fmt.Println("Diana 不存在")
}
// 添加或修改键值对
studentScores["Eve"] = 98
fmt.Println("更新后:", studentScores)
}
说明:
map是引用类型,传递时不会复制整个结构。- 使用
key, ok := map[key]可以判断键是否存在。map无序,不保证遍历时的顺序。
结构体与方法
结构体(struct)是 Go 中组织数据的常用方式,类似于其他语言的“类”或“结构体”。
package main
import "fmt"
// 定义一个结构体:Person
type Person struct {
Name string
Age int
City string
}
// 为 Person 添加方法:介绍自己
func (p Person) introduce() {
fmt.Printf("大家好,我是 %s,今年 %d 岁,来自 %s。\n", p.Name, p.Age, p.City)
}
// 可以通过指针接收者修改结构体
func (p *Person) updateCity(newCity string) {
p.City = newCity
}
func main() {
// 创建结构体实例
person := Person{Name: "李明", Age: 30, City: "北京"}
// 调用方法
person.introduce()
// 更新城市
person.updateCity("上海")
person.introduce()
}
说明:
func (p Person) introduce()是值接收者,不会修改原结构体。func (p *Person) updateCity()是指针接收者,可以修改原数据。- 方法可以绑定到任何类型,包括自定义类型和内置类型。
Go 语言基础语法是理解整个语言生态的基石。从变量声明、控制流程到函数、数据结构,每一步都体现了 Go 的简洁与高效。掌握这些内容,你就能写出结构清晰、运行稳定的 Go 程序。
无论是构建后端服务,还是编写工具脚本,Go 语言基础语法都能为你打下坚实基础。建议你动手写一写代码,边学边练,才能真正掌握。