第一次提交
This commit is contained in:
643
src/programming/backend/go/go基础入门.md
Normal file
643
src/programming/backend/go/go基础入门.md
Normal file
@@ -0,0 +1,643 @@
|
||||
---
|
||||
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!
|
||||
Reference in New Issue
Block a user