--- icon: mdi:language-go date: 2025-05-22 category: - 后端开发 - Go语言 tag: - Go - 编程语言 - 入门教程 star: true --- # Go 语言基础入门 Go(又称 Golang)是由 Google 开发的一种静态强类型、编译型、并发型,并具有垃圾回收功能的编程语言。它于 2009 年首次发布,以其简洁、高效和强大的并发处理能力而闻名。 ## 目录 1. [Go 语言简介](#go-语言简介) 2. [环境搭建](#环境搭建) 3. [第一个 Go 程序](#第一个-go-程序) 4. [基本语法](#基本语法) 5. [数据类型](#数据类型) 6. [变量和常量](#变量和常量) 7. [运算符](#运算符) 8. [控制结构](#控制结构) 9. [函数](#函数) 10. [数组和切片](#数组和切片) 11. [映射(Map)](#映射map) 12. [结构体](#结构体) 13. [接口](#接口) 14. [并发编程](#并发编程) 15. [错误处理](#错误处理) 16. [包管理](#包管理) ## Go 语言简介 Go 语言的设计目标是: - 简单易学:语法简洁,去除了许多其他语言的复杂特性 - 高效执行:编译型语言,运行速度快 - 内置并发支持:通过 goroutine 和 channel 实现轻量级并发 - 强大的标准库:提供了丰富的内置库 - 跨平台支持:支持多种操作系统和架构 ## 环境搭建 ### 下载安装 1. 访问 [Go 官方网站](https://golang.org/dl/) 下载适合你操作系统的安装包 2. Windows 用户下载 `.msi` 文件,macOS 用户下载 `.pkg` 文件,Linux 用户下载 `.tar.gz` 文件 ### Windows 安装步骤 1. 双击下载的 `.msi` 文件开始安装 2. 默认会安装到 `C:\Go\` 目录下 3. 安装完成后会自动配置环境变量 ### Linux 安装步骤 ```bash # 下载 Go 安装包 wget https://golang.org/dl/go1.19.linux-amd64.tar.gz # 解压到 /usr/local 目录 sudo tar -C /usr/local -xzf go1.19.linux-amd64.tar.gz # 配置环境变量 echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.bashrc source ~/.bashrc ``` ### 验证安装 打开终端或命令提示符,输入以下命令验证是否安装成功: ```bash go version ``` 如果显示版本信息,则说明安装成功。 ### 设置工作目录 Go 项目推荐使用模块化管理,在任意目录下创建你的项目文件夹: ```bash mkdir myproject cd myproject go mod init myproject ``` ## 第一个 Go 程序 创建一个名为 `main.go` 的文件: ```go package main import "fmt" func main() { fmt.Println("Hello, World!") } ``` 运行程序: ```bash go run main.go ``` 或者编译后运行: ```bash go build main.go ./main ``` 代码解释: - `package main`:声明这是一个可执行程序的主包 - `import "fmt"`:导入格式化输入输出包 - `func main()`:程序入口函数 - `fmt.Println()`:打印文本并换行 ## 基本语法 ### 注释 ```go // 单行注释 /* 多行注释 可以跨越多行 */ ``` ### 标识符命名规则 - 只能包含字母、数字和下划线 - 不能以数字开头 - 区分大小写 - 不能是关键字 ### 关键字 Go 语言有 25 个关键字: ``` break default func interface select case defer go map struct chan else goto package switch const fallthrough if range type continue for import return var ``` ## 数据类型 Go 语言的数据类型分为四大类: ### 基本类型 1. **布尔型**:bool(true/false) 2. **数字类型**: - 整数型:int8, int16, int32, int64, uint8, uint16, uint32, uint64, int, uint, uintptr - 浮点型:float32, float64 - 复数型:complex64, complex128 3. **字符串类型**:string 4. **派生类型**: - 指针类型(Pointer) - 数组类型 - 结构化类型(struct) - Channel 类型 - 函数类型 - 切片类型 - 接口类型(interface) - Map 类型 ### 类型示例 ```go var a bool = true // 布尔型 var b int = 10 // 整型 var c float32 = 3.14 // 浮点型 var d string = "Hello" // 字符串 var e complex64 = 3+4i // 复数型 ``` ## 变量和常量 ### 变量声明 四种声明变量的方式: ```go // 1. 指定变量类型,声明后若不赋值则使用默认值 var v1 int // 2. 根据值自行判定变量类型 var v2 = 10 // 3. 省略 var,注意 := 左侧的变量必须是未声明过的 v3 := 10 // 4. 多变量声明 var v4, v5 int = 1, 2 var v6, v7 = 3, "hello" v8, v9 := 5, true ``` ### 变量作用域 - **局部变量**:在函数内声明,只在函数内有效 - **全局变量**:在函数外声明,在整个包内有效 ### 常量声明 ```go const PI = 3.14159 const NAME = "Golang" // 常量组 const ( Monday = 1 Tuesday = 2 Wednesday = 3 ) ``` ### iota iota 是一个特殊的常量,用于生成一组相似的常量值: ```go const ( a = iota // 0 b // 1 c // 2 d // 3 ) ``` ## 运算符 ### 算术运算符 | 运算符 | 描述 | |--------|------| | + | 相加 | | - | 相减 | | * | 相乘 | | / | 相除 | | % | 求余 | | ++ | 自增 | | -- | 自减 | ### 关系运算符 | 运算符 | 描述 | |--------|------| | == | 相等 | | != | 不相等 | | > | 大于 | | < | 小于 | | >= | 大于等于 | | <= | 小于等于 | ### 逻辑运算符 | 运算符 | 描述 | |--------|------| | && | 逻辑与 | | \|\| | 逻辑或 | | ! | 逻辑非 | ### 位运算符 | 运算符 | 描述 | |--------|------| | & | 按位与 | | \| | 按位或 | | ^ | 按位异或 | | << | 左移 | | >> | 右移 | ## 控制结构 ### 条件语句 if ```go if condition { // code } // 带初始化语句 if x := 10; x > 5 { fmt.Println("x 大于 5") } else { fmt.Println("x 小于等于 5") } ``` ### 循环语句 for Go 只有一种循环结构:for 循环 ```go // 基本 for 循环 for i := 0; i < 10; i++ { fmt.Println(i) } // while 形式的循环 i := 0 for i < 10 { fmt.Println(i) i++ } // 无限循环 for { // 死循环 } ``` ### 选择语句 switch ```go switch day { case 1: fmt.Println("Monday") case 2: fmt.Println("Tuesday") default: fmt.Println("Unknown day") } // 不带条件的 switch switch { case score >= 90: fmt.Println("优秀") case score >= 80: fmt.Println("良好") default: fmt.Println("一般") } ``` ## 函数 ### 函数定义 ```go func functionName(parameterName type) returnType { // 函数体 return returnValue } ``` ### 示例 ```go // 简单函数 func add(a int, b int) int { return a + b } // 多返回值函数 func swap(x, y string) (string, string) { return y, x } // 可变参数函数 func sum(nums ...int) int { total := 0 for _, num := range nums { total += num } return total } ``` ### 函数调用 ```go result := add(3, 5) a, b := swap("hello", "world") total := sum(1, 2, 3, 4, 5) ``` ### defer 语句 defer 用于延迟执行函数,通常用于资源清理: ```go func readFile() { file, err := os.Open("file.txt") if err != nil { log.Fatal(err) } defer file.Close() // 函数结束前关闭文件 // 处理文件... } ``` ## 数组和切片 ### 数组 数组是固定长度的序列: ```go // 声明数组 var arr1 [5]int // 长度为 5 的整型数组 arr2 := [5]int{1, 2, 3, 4, 5} // 初始化数组 arr3 := [...]int{1, 2, 3} // 根据元素个数确定长度 // 访问数组元素 fmt.Println(arr2[0]) // 输出 1 arr2[1] = 10 // 修改元素 ``` ### 切片 切片是对数组的抽象,长度可变: ```go // 创建切片 slice1 := []int{1, 2, 3} // 直接创建切片 slice2 := make([]int, 5) // 创建长度为 5 的切片 slice3 := make([]int, 3, 5) // 长度为 3,容量为 5 // 从数组创建切片 arr := [5]int{1, 2, 3, 4, 5} slice4 := arr[1:4] // 包含索引 1 到 3 的元素 // 切片操作 slice5 := append(slice1, 4, 5) // 添加元素 len(slice1) // 获取长度 cap(slice1) // 获取容量 ``` ## 映射(Map) Map 是一种无序的键值对集合: ```go // 创建 map var m1 map[string]int // 声明但未初始化 m2 := make(map[string]int) // 使用 make 初始化 m3 := map[string]int{ // 直接初始化 "apple": 5, "banana": 3, } // 操作 map m2["orange"] = 10 // 添加键值对 value := m2["orange"] // 获取值 delete(m2, "orange") // 删除键值对 // 检查键是否存在 if val, ok := m2["apple"]; ok { fmt.Println("apple:", val) } else { fmt.Println("apple not found") } ``` ## 结构体 结构体是一种用户自定义的数据类型,允许我们组合不同类型的字段: ```go // 定义结构体 type Person struct { Name string Age int Email string } // 创建结构体实例 person1 := Person{Name: "张三", Age: 25, Email: "zhangsan@example.com"} person2 := Person{"李四", 30, "lisi@example.com"} person3 := Person{} // 所有字段使用零值 // 访问结构体字段 fmt.Println(person1.Name) person1.Age = 26 // 结构体指针 person4 := &Person{Name: "王五", Age: 28} fmt.Println(person4.Name) // 自动解引用 ``` ### 方法 方法是带有接收者的函数: ```go // 为结构体定义方法 func (p Person) SayHello() { fmt.Printf("Hello, I'm %s\n", p.Name) } func (p *Person) SetAge(age int) { p.Age = age } // 调用方法 person1.SayHello() person1.SetAge(27) ``` ## 接口 接口是一组方法签名的集合: ```go // 定义接口 type Shape interface { Area() float64 Perimeter() float64 } // 实现接口 type Rectangle struct { Width, Height float64 } func (r Rectangle) Area() float64 { return r.Width * r.Height } func (r Rectangle) Perimeter() float64 { return 2 * (r.Width + r.Height) } // 使用接口 var s Shape = Rectangle{Width: 10, Height: 5} fmt.Println("Area:", s.Area()) fmt.Println("Perimeter:", s.Perimeter()) ``` ## 并发编程 Go 语言内置了强大的并发支持,主要包括 goroutine 和 channel。 ### Goroutine Goroutine 是轻量级线程: ```go // 启动 goroutine go func() { fmt.Println("Hello from goroutine") }() // 启动多个 goroutine for i := 0; i < 5; i++ { go func(n int) { fmt.Printf("Goroutine %d\n", n) }(i) } ``` ### Channel Channel 用于 goroutine 之间通信: ```go // 创建 channel ch := make(chan int) // 发送数据到 channel go func() { ch <- 42 }() // 从 channel 接收数据 value := <-ch fmt.Println(value) // 带缓冲的 channel bufferedCh := make(chan int, 3) bufferedCh <- 1 bufferedCh <- 2 bufferedCh <- 3 ``` ### Select Select 用于在多个 channel 操作中进行选择: ```go select { case msg1 := <-ch1: fmt.Println("Received", msg1) case msg2 := <-ch2: fmt.Println("Received", msg2) case <-time.After(time.Second): fmt.Println("Timeout") } ``` ## 错误处理 Go 语言通过返回错误值来进行错误处理: ```go // 错误处理示例 func divide(a, b float64) (float64, error) { if b == 0 { return 0, errors.New("division by zero") } return a / b, nil } // 使用错误 result, err := divide(10, 0) if err != nil { fmt.Println("Error:", err) } else { fmt.Println("Result:", result) } ``` ### 自定义错误 ```go type MyError struct { Msg string Code int } func (e *MyError) Error() string { return fmt.Sprintf("Error %d: %s", e.Code, e.Msg) } ``` ## 包管理 ### 创建模块 ```bash go mod init myproject ``` ### 添加依赖 ```bash go get github.com/gin-gonic/gin ``` ### 查看依赖 ```bash go mod tidy go list -m all ``` ### go.mod 文件示例 ``` module myproject go 1.19 require ( github.com/gin-gonic/gin v1.8.1 ) ``` ## 总结 Go 语言以其简洁的语法、强大的并发支持和高效的执行性能成为现代软件开发的重要选择。通过本文档的学习,你应该掌握了 Go 语言的基本概念和语法,可以开始编写简单的 Go 程序了。 建议接下来的学习路径: 1. 练习更多 Go 语言编程题目 2. 学习标准库的使用 3. 了解 Go 语言的最佳实践 4. 尝试构建实际项目 Happy coding with Go!