Go语言基础语法快速入门
Go语言基础语法快速入门:开启你的Go编程之旅
Go(又称Golang)是Google开发的一种开源编程语言,以其简洁、高效和强大的并发处理能力而备受开发者青睐。无论你是编程新手,还是希望扩展技能树的资深开发者,Go语言都是一个绝佳的选择。
这篇博客将带你快速掌握Go语言的基础语法,为你后续的深入学习打下坚实的基础。
1. 万物之始:Hello, World
让我们从每个程序员都熟悉的Hello, World开始,一窥Go程序的基本结构。
package main
import "fmt"
func main() {
fmt.Println("Hello, World")
}这段代码虽短,却包含了Go语言的核心组件:
package main: 每个Go程序都由包(package)组成。package main定义了该文件属于main包,表明它是一个可独立执行的程序。import "fmt":import关键字用于导入其他包。fmt是Go语言的标准库之一,提供了格式化的输入输出功能,例如打印到控制台。func main() { ... }:func关键字用于声明一个函数。main函数是程序的入口点,程序会从这里开始执行。fmt.Println("Hello, World"): 调用fmt包中的Println函数,将字符串"Hello, World"输出到控制台,并自动换行。
2. 变量与常量:程序数据的基石
在Go中,我们使用变量和常量来存储和管理数据。
变量(Variables)
变量是值的存储位置,其值在程序运行期间可以改变。Go语言是静态类型语言,意味着在声明变量时必须指定其类型。
声明变量的方式:
var关键字(标准声明)// 声明一个名为 age 的整数变量 var age int age = 30 // 赋值 // 声明并同时初始化 var name string = "Alice"类型推断
如果在声明时就进行初始化,Go可以自动推断变量的类型,此时可以省略类型说明。
var score = 100 // Go 会推断 score 是 int 类型短变量声明
:=在函数内部,可以使用更简洁的
:=操作符进行声明和初始化。这是最常用的方式。// 只能在函数内部使用 country := "USA" isReady := true
常量(Constants)
常量的值在编译时就已经确定,程序运行期间不可更改。
const PI = 3.14159
const AppName = "My Awesome App"3. 基础数据类型
Go语言内置了丰富的数据类型,主要分为以下几类:
- 布尔型 (bool): 值为
true或false。 - 数值类型:
- 整数 (int): 包括
int,int8,int16,int32,int64(有符号) 和uint,uint8,uint16,uint32,uint64(无符号)。 - 浮点数 (float):
float32,float64。 - 复数 (complex):
complex64,complex128。
- 整数 (int): 包括
- 字符串 (string): 一个由字节组成的序列,通常用于表示文本。字符串是不可变的。
var isActive bool = true
var temperature float64 = 98.6
var message string = "学习Go语言很有趣!"4. 控制流程:指挥程序的执行路径
控制流程语句决定了代码的执行顺序。
if-else 条件语句
if-else 用于根据条件执行不同的代码块。
score := 85
if score >= 90 {
fmt.Println("优秀")
} else if score >= 60 {
fmt.Println("及格")
} else {
fmt.Println("需要努力")
}特色语法:if 语句可以包含一个简短的初始化语句,其声明的变量作用域仅限于该if-else块。
if num := 10; num%2 == 0 {
fmt.Println(num, "是偶数")
} else {
fmt.Println(num, "是奇数")
}好的 👍 我来帮你把 数组、切片、map、字符串、channel 的遍历 示例也补充进来,保持和你现有的笔记风格一致。
for 循环
Go 语言只有一种循环结构——for 循环,但它有多种形式。
- 标准的
for循环
for i := 0; i < 5; i++ {
fmt.Println(i)
}- 类似
while的循环
sum := 1
for sum < 100 {
sum += sum
}
fmt.Println(sum)- 无限循环
for {
// 无限循环,需要使用 break 来退出
break
}- 遍历数组 / 切片
nums := []int{10, 20, 30, 40}
for i, v := range nums {
fmt.Println("索引:", i, "值:", v)
}如果只关心值,可以写成:
for _, v := range nums {
fmt.Println(v)
}- 遍历 map
m := map[string]int{"a": 1, "b": 2, "c": 3}
for k, v := range m {
fmt.Println("键:", k, "值:", v)
}- 遍历字符串
Go 的字符串是 UTF-8 编码,for range 会自动按 字符 (rune) 遍历,而不是字节:
s := "你好Go"
for i, r := range s {
fmt.Printf("索引 %d 字符 %c\n", i, r)
}- 遍历 channel
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch)
for v := range ch {
fmt.Println(v)
}switch 选择语句
switch 是一个更清晰的多路分支选择。Go的switch更加灵活,它会自动在每个case后添加break。
day := "Sunday"
switch day {
case "Monday", "Tuesday", "Wednesday", "Thursday", "Friday":
fmt.Println("工作日")
case "Saturday", "Sunday":
fmt.Println("周末")
default:
fmt.Println("无效的输入")
}switch 同样支持初始化语句,并且case后面可以跟表达式。
5. 函数(Functions)
函数是执行特定任务的代码块,是组织和重用代码的基本方式。
// 接收两个整数并返回它们的和
func add(a int, b int) int {
return a + b
}
// 调用函数
result := add(5, 3) // result is 8多返回值是Go语言的一大特色,常用于返回结果和错误信息。
func divide(a, b int) (int, error) {
if b == 0 {
return 0, fmt.Errorf("除数不能为零")
}
return a / b, nil // nil 表示没有错误
}
quotient, err := divide(10, 2)
if err != nil {
fmt.Println("错误:", err)
} else {
fmt.Println("商是:", quotient)
}函数内定义函数
Go 不允许像 Python、JS 那样直接在函数内再定义命名函数, 但是可以通过 匿名函数 + 变量赋值 的方式来实现“函数内函数”,并且可以递归。
// 前序遍历和中序遍历构建二叉树
func buildTree(preorder []int, inorder []int) *TreeNode {
index := map[int]int{}
for i, x := range inorder {
index[x] = i
}
// 声明 dfs 的函数类型
var dfs func(preL, preR, inL, inR int) *TreeNode
// 定义 dfs 为匿名函数
dfs = func(preL, preR, inL, inR int) *TreeNode {
if preL == preR {
return nil
}
leftSize := index[preorder[preL]] - inL
left := dfs(preL+1, preL+1+leftSize, inL, inL+leftSize)
right := dfs(preL+1+leftSize, preR, inL+1+leftSize, inR)
return &TreeNode{preorder[preL], left, right}
}
return dfs(0, len(preorder), 0, len(inorder))
}6. 复合数据类型:组织数据集合
数组 (Array)
数组是固定长度的、包含相同类型元素的序列。
var numbers [3]int // 声明一个长度为3的整数数组
numbers[0] = 1
numbers[1] = 2
numbers[2] = 3
// 声明并初始化
primes := [5]int{2, 3, 5, 7, 11}切片 (Slice)
切片是对数组一个连续片段的引用,它比数组更常用,因为其长度是可变的。
// 创建一个切片
scores := []int{88, 92, 77}
// 添加元素
scores = append(scores, 95)
// 切片操作
subSlice := scores[1:3] // 包含索引1和2的元素: [92, 77]映射 (Map)
Map 是一种无序的键值对集合,类似于其他语言中的哈希表或字典。
// 创建一个key为string,value为int的map
ages := make(map[string]int)
ages["Alice"] = 30
ages["Bob"] = 25
fmt.Println("Alice的年龄是:", ages["Alice"])
// 删除键值对
delete(ages, "Bob")好的 👍 这篇博客已经覆盖了 Go 的基础语法(变量、常量、控制流、函数、数组、切片、map)。为了更完整地作为「Go 语言基础快速入门」,我建议再补充几个 Go 中非常常用的语法点:指针、结构体、方法、接口、并发(goroutine 与 channel)。这样文章就能形成一个比较完整的入门教程。下面我在你的文章基础上继续补充。
7. 指针(Pointers)
Go 语言支持指针,但语法比 C/C++ 更简洁。指针保存的是某个值在内存中的地址。
func main() {
x := 10
p := &x // p 保存变量 x 的地址
fmt.Println("x 的值:", x)
fmt.Println("x 的地址:", p)
fmt.Println("通过指针取值:", *p)
*p = 20 // 修改指针指向的值
fmt.Println("修改后的 x:", x)
}要点:
&取变量地址*通过指针访问值- Go 没有指针运算(不像 C 那样可以
p++),更安全
8. 结构体(Struct)
结构体用于定义和组合复杂的数据类型。
type Person struct {
Name string
Age int
}
func main() {
// 初始化结构体
p1 := Person{Name: "Alice", Age: 30}
p2 := Person{"Bob", 25} // 省略字段名,但不推荐
// 访问字段
fmt.Println(p1.Name, p1.Age)
// 取地址修改
p3 := &Person{Name: "Charlie"}
p3.Age = 28
fmt.Println(p3)
}9. 方法(Methods)
方法是和结构体(或其他自定义类型)绑定的函数。
type Rectangle struct {
Width, Height float64
}
// 值接收者
func (r Rectangle) Area() float64 {
return r.Width * r.Height
}
// 指针接收者
func (r *Rectangle) Scale(factor float64) {
r.Width *= factor
r.Height *= factor
}
func main() {
rect := Rectangle{3, 4}
fmt.Println("面积:", rect.Area())
rect.Scale(2)
fmt.Println("缩放后:", rect.Area())
}规则:值接收者不会修改原始数据,指针接收者可以修改。
10. 接口(Interfaces)
接口定义了一组方法,只要某个类型实现了这些方法,就自动实现了接口(无需显式声明)。
type Shape interface {
Area() float64
}
type Circle struct {
Radius float64
}
func (c Circle) Area() float64 {
return 3.14 * c.Radius * c.Radius
}
func main() {
var s Shape = Circle{5}
fmt.Println("圆的面积:", s.Area())
}接口在 Go 中非常常用,用于解耦和多态。
11. 并发:Goroutine 与 Channel
Go 的最大特色是并发。
Goroutine:轻量级线程
func printMessage(msg string) {
for i := 0; i < 3; i++ {
fmt.Println(msg)
}
}
func main() {
go printMessage("Hello") // 开启一个新的 goroutine
printMessage("World") // 主 goroutine
}Channel:用于 goroutine 之间通信
func worker(ch chan string) {
ch <- "任务完成" // 发送消息
}
func main() {
ch := make(chan string)
go worker(ch)
msg := <-ch // 接收消息
fmt.Println(msg)
}Channel 保证 goroutine 之间安全通信,避免手动加锁。
12. 错误处理
Go 没有异常机制,使用 返回值 + error 来处理错误。
import "errors"
func divide(a, b int) (int, error) {
if b == 0 {
return 0, errors.New("除数不能为零")
}
return a / b, nil
}
func main() {
result, err := divide(10, 0)
if err != nil {
fmt.Println("错误:", err)
} else {
fmt.Println("结果:", result)
}
}13. defer、panic 和 recover
defer:函数结束前延迟执行(常用于资源释放)panic:触发运行时错误recover:捕获 panic,防止程序崩溃
func safeDivide(a, b int) {
defer fmt.Println("结束 safeDivide") // 延迟执行
if b == 0 {
panic("除数不能为零") // 抛出异常
}
fmt.Println("结果:", a/b)
}
func main() {
defer func() {
if r := recover(); r != nil {
fmt.Println("捕获错误:", r)
}
}()
safeDivide(10, 0)
}