My Little World

语法 3

Go语言常用标准库详解

1. 语法讲解

Go语言标准库提供了丰富的基础功能包,以下是最核心和常用的库:

  • fmt包:格式化I/O操作,类似C语言的printf和scanf
  • os包:操作系统功能接口,文件操作、环境变量、进程管理
  • io包:基础I/O接口抽象,Reader/Writer接口
  • strings包:字符串操作函数
  • strconv包:字符串与基本类型转换
  • time包:时间日期处理
  • encoding/json包:JSON编码解码
  • net/http包:HTTP客户端和服务器
  • sync包:并发同步原语
  • flag包:命令行参数解析

2. 应用场景

  • fmt/os/io:系统工具开发、配置文件管理、日志处理
  • strings/strconv:用户输入验证、数据清洗、格式转换
  • time:定时任务、缓存过期、时间戳管理
  • encoding/json:API开发、配置文件解析、数据序列化
  • net/http:Web服务、微服务、API网关
  • sync:并发编程、资源共享、性能优化

练习

字符串处理(strings/split/join/trim等函数、正则表达式regexp)

1. 语法讲解

Go语言的 strings 包提供了丰富的字符串操作函数,strconv 包处理字符串与基本类型的转换,regexp 包提供正则表达式功能。

字符串特点:Go中字符串是不可变的字节序列,使用UTF-8编码。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127

package main

import (
"fmt"
"regexp"
"strconv"
"strings"
"unicode/utf8"
)

func validateEmail(email string) bool {
pattern := `^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$`
match, _ := regexp.MatchString(pattern, email)
return match
}

func validatePhone(phoneNumber string) bool {
pattern := `^1[2-9]\d{9}$`
match, _ := regexp.MatchString(pattern, phoneNumber)
return match
}

// input: john doe:25:john@example.com
func ProcessUserInfo(userInfo string) map[string]interface{} {
result := make(map[string]interface{})
cleaned := strings.TrimSpace(userInfo)
cleaned = strings.ToLower(cleaned)
// 解析用户信息
parts := strings.Split(cleaned, ":")
if len(parts) != 3 {
result["error"] = "用户信息格式错误"
return result
}
// 存储用户信息
result["name"] = parts[0]
age, err := strconv.Atoi(strings.TrimSpace(parts[1]))
if err != nil {
result["error"] = "年龄格式错误"
} else {
result["age"] = age
}
email := strings.TrimSpace(parts[2])
if !validateEmail(email) {
result["email"] = "Invalid email"
} else {
result["email"] = email
}

result["origin_length"] = len(userInfo)
result["cleaned_length"] = len(cleaned)
result["rune_count"] = utf8.RuneCountInString(userInfo)
return result
}

func main() {

users := []string{
"john doe:25:john@example.com",
"jane doe:30:jane@example.com",
"jim doe:35:jim@example.com",
"嗨嗨:30:jane@example.com",
}
for _, user := range users {
result := ProcessUserInfo(user)
for key, value := range result {
fmt.Printf("%s: %v\n", key, value)
}
fmt.Println("-----------------")
}

phoneNumbers := []string{
"13800138000",
"13800138001",
"13800138002",
"13800138003",
}
for _, phoneNumber := range phoneNumbers {
if validatePhone(phoneNumber) {
fmt.Printf("Valid phone number: %s\n", phoneNumber)
} else {
fmt.Printf("Invalid phone number: %s\n", phoneNumber)
}
}

// 字符串构造器
var builder strings.Builder
builder.WriteString("Hello, ")
products := []string{"中国", "美国"}
for _, v := range products {
builder.WriteString(v)
builder.WriteString("\n")
}
fmt.Println(builder.String())

// 字符串替换和重复
template := "重要通知: {message} | 重复显示: {repeat}"
replaced := strings.Replace(template, "{message}", "系统维护通知", 1)
repeated := strings.Repeat("注意!", 3)
final := strings.Replace(replaced, "{repeat}", repeated, 1)
fmt.Println(final)

// 字符串前缀和后缀
var (
str string
str2 string
)
str = "This is a test string."
str2 = "This is a test string."
if str == str2 {
fmt.Println("字符串相等")
}

url1 := "https://test.com/api/v1/users"
url2 := "https://test.com/api/v1/products"

if strings.HasPrefix(url1, "https://") && strings.HasSuffix(url1, "users") {
fmt.Println("有效的URL")
} else {
fmt.Println("无效的URL")
}

if strings.HasPrefix(url2, "https://") && strings.HasSuffix(url2, ".com") {
fmt.Println("有效的URL")
}

}

2. 应用场景

  • strings包:用户输入验证、文本解析、数据清洗、URL处理
  • strconv包:配置文件数值转换、命令行参数转换、数据库数据转换
  • regexp包:邮箱/手机号验证、复杂文本提取、数据格式标准化、日志分析

练习

时间与日期(time包、时间格式化、定时任务)

1. 语法讲解

Go语言的 time 包提供了时间的显示和测量功能,日历计算采用公历。

  • 时间类型:time.Time 表示时间点
  • 时间间隔:time.Duration 表示时间段,单位纳秒
  • 时间格式化:使用特定参考时间进行格式化(2006-01-02 15:04:05)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
package main

import (
"fmt"
"time"
)

func main() {
now := time.Now()
fmt.Println(now)
fmt.Println(now.Format("2006-01-02 15:04:05"))

// 获取3分钟后的时间
threeMinutesFromNow := now.Add(3 * time.Minute)
fmt.Println("3分钟后的时间:")
fmt.Println(threeMinutesFromNow)
fmt.Println(threeMinutesFromNow.Format("2006-01-02 15:04:05"))

// 获取5天后时间
fiveDaysFromNow := now.AddDate(0, 0, 5)
fmt.Println("5天后的时间:")
fmt.Println(fiveDaysFromNow)
fmt.Println(fiveDaysFromNow.Format("2006-01-02 15:04:05"))

// 获取5天前时间
fiveDaysAgo := now.AddDate(0, 0, -5)
fmt.Println("5天前的时间:")
fmt.Println(fiveDaysAgo)
fmt.Println(fiveDaysAgo.Format("2006-01-02 15:04:05"))

// 计算两个时间之间的差值 天级
diff := fiveDaysFromNow.Sub(fiveDaysAgo).Hours() / 24
fmt.Println("5天前到5天后的天数:")
fmt.Println(diff)

// 哪个时间更大
fmt.Println("now是否大于threeMinutesFromNow:")
fmt.Println(now.After(threeMinutesFromNow))
fmt.Println("now是否小于threeMinutesFromNow:")
fmt.Println(now.Before(threeMinutesFromNow))

// 指定时区
fmt.Println("now的时间区:")
fmt.Println(now.In(time.Local))
fmt.Println(now.In(time.UTC))

fmt.Println(now.Format(time.DateTime)) // 实际格式化规则固定

loc, _ := time.LoadLocation("America/New_York")
nyTime := time.Now().In(loc)
fmt.Println("修改后时间区:")
fmt.Println(nyTime.Format(time.DateTime))

// 解析时间字符串
dtime := "2025-10-18 14:23:12"
ddtime, _ := time.Parse(time.DateTime, dtime)
fmt.Println("解析后的时间:")
fmt.Println(ddtime.Format(time.DateTime))

// 时间周期
start := time.Date(2025, 1, 1, 0, 0, 0, 0, time.Local)
end := time.Date(2026, 1, 1, 0, 0, 0, 0, time.Local)
days := end.Sub(start).Hours() / 24
fmt.Println("2025年1月1日到2026年1月1日的天数:")
fmt.Println(days)

}

2. 应用场景

  • 时间获取与计算:日志时间戳、用户注册时间、订单创建时间、缓存过期控制
  • 定时任务:定时数据备份、周期性报表生成、缓存刷新、消息队列处理
  • 时间格式化:前端显示、API响应、报表导出、国际化时间显示

练习

反射

1. 语法/理论讲解

  • 定义:程序在运行时检查自身结构的能力
  • 核心:interface{} + reflect 包
  • 像程序运行时的“镜子”,能看到自己的类型信息

两大核心组件

1
2
3
4
5
6
7
8
import "reflect"

// 1. Type - 类型信息
var x int = 42
t := reflect.TypeOf(x) // 获取类型信息

// 2. Value - 值信息
v := reflect.ValueOf(x) // 获取值信息

关键概念

  • Kind:基础类型(int、string、struct等)
  • 可设置性:值能否被修改
  • 类型断言:运行时类型检查

性能注意事项

  • 反射比直接调用慢10-100倍
  • 生产环境避免在热点路径使用
  • 可提前缓存反射结果

2. 应用场景

1. 框架开发

  • Web框架中的路由绑定和参数解析
  • 各类注入的中间件

2. 配置解析

  • JSON/YAML配置文件 → 结构体
  • 根据字段标签动态映射

3. 序列化/反序列化

  • JSON、XML编码解码
  • 数据库ORM映射

4. 依赖注入

  • 自动创建对象实例
  • 解析依赖关系

3. 总结

  1. 反射是什么:运行时类型检查能力
  2. 核心API:TypeOf()、ValueOf()、MethodByName()、Call()
  3. 应用场景:框架、配置、ORM、依赖注入
  4. 使用原则:谨慎使用,注意性能

4. 如无必要,不用反射

  1. 与反射相关的代码,经常是难以阅读的。在软件工程中,代码可读性也是一个非常重要的指标。
  2. Go 语言作为一门静态语言,编码过程中,编译器能提前发现一些类型错误,但是对于反射代码是无能为力的。所以包含反射相关的代码,很可能会运行很久,才会出错,这时候经常是直接 panic,可能会造成严重的后果。
  3. 反射对性能影响还是比较大的,比正常代码运行速度慢一到两个数量级。所以,对于一个项目中处于运行效率关键位置的代码,尽量避免使用反射特性。

【抽象和性能之间取平衡】

练习

Go语言泛型

1. 语法/理论讲解

  • 定义:编写适用于多种类型的代码,避免重复
  • 核心:类型参数 + 类型约束
  • 像写函数的”模板”,可以适配不同类型

基本语法

1
2
3
4
5
6
7
8
9
// 泛型函数
func 函数名[T 约束](参数 T) T {
// 函数体
}

// 泛型结构体
type 结构体名[T 约束] struct {
字段 T
}

关键概念

  • 类型参数:函数或类型定义中的占位类型
  • 类型约束:限制类型参数的范围
  • 类型推断:编译器自动推断类型参数
  • 可比较性:类型是否支持 == 和 != 操作

为什么要用泛型?

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 传统方式:为每种类型写重复代码
func MaxInt(a, b int) int {
if a > b { return a }
return b
}

func MaxFloat(a, b float64) float64 {
if a > b { return a }
return b
}

// 泛型方式:一个函数搞定
func Max[T comparable](a, b T) T {
if a > b { return a }
return b
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
// [T 类型范围]
// T any 不指定任何类型,可以是任意类型
func Println[T any](v []T) {
for _, item := range v {
fmt.Println(item)
}
}

// T comparable 可比较的类型,可以是任意可比较的类型,能进行 == 或者!= 操作
// 例如 int, float64, string, bool 等
func FoundIndex[T comparable](v []T, item T) int {
for i, v := range v {
if v == item {
return i
}
}
return -1
}

// T cmp.Ordered,这里的类型范围是cmp.Ordered,可以排序的, 可以进行> < 操作
//
// 例如 int, float64, string 等
func Max[T cmp.Ordered](v []T) (T, int) {
pos := 0
maxVal := v[pos]
for i, v := range v {
if maxVal < v {
maxVal = v
pos = i
}
}
return maxVal, pos
}

// 将T 指定为自定义类型
type Stringer interface {
CustomPrintln(str string) string
}

func ForStringer[T Stringer](v []T) {
for _, item := range v {
item.CustomPrintln("其他信息")
}
}

type Person struct {
Name string
Age int
}

func (p Person) CustomPrintln(s string) string {
fmt.Printf("名字%s, 年龄: %d 其他: %s\n", p.Name, p.Age, s)
return p.Name
}

// 自定义类型,指定某几类数据
type MyNumber interface {
~int | ~float64
}

func Sum[T MyNumber](v []T) T {
var sum T
for _, v := range v {
sum += v
}
return sum
}

// 定义一个通用的Map结构体,用于存储键值对
// K 可比较的类型, V 任意类型
type Pair[K comparable, V any] struct {
Key K
Value V
}

2. 应用场景

1. 通用数据结构

  • 栈、队列、链表等容器
  • 集合操作

2. 工具函数

  • 比较、排序、查找
  • 数学运算

3. 数据处理

  • 映射、过滤、归约操作
  • 数据转换

4. 避免interface{}和类型断言

  • 类型安全
  • 更好的性能

3.总结

  1. 泛型是什么:编写类型安全的通用代码 【编译时就知道了数据类型】
  2. 核心语法:[T 约束]、any、comparable、自定义约束
  3. 应用场景:通用数据结构、工具函数、数据处理
  4. 优势:类型安全、减少重复代码、更好性能
  5. 使用原则:在真正需要代码复用时使用,不要过度设计 【代码复用和过度设计之间取平衡】

练习

Go语言工具链详解

1. 工具讲解

Go语言工具链是Go开发的核心组件,提供完整的代码管理、编译、测试功能。

  • go mod:Go模块依赖管理,从Go 1.11开始引入的官方依赖管理工具
  • go build:编译Go程序,生成可执行文件
  • go run:编译并直接运行Go程序 , 同一个文件夹下面文件的package 名相同,同时运行的话,每个文件都要指定 go run main.go tool.go
  • go test:运行测试,支持单元测试、基准测试和示例测试
  • go get:添加依赖包到模块
  • go install:编译并安装包或命令
  • go fmt:格式化代码
  • go vet:静态代码分析
  • go doc:查看文档

2. 应用场景

  • go mod:项目初始化、依赖管理、团队协作
  • go build:生产环境编译、跨平台部署
  • go run:快速开发测试、演示示例
  • go test:单元测试、性能基准测试、代码覆盖率、CI/CD流水线
    go test -bench=. ./calculator/ 性能测试 go test -cover ./calculator/ 计算覆盖率
    ** go test -v ./calculator/ 打印详细测试信息
  • go fmt/vet:代码质量保证、团队编码规范、代码审查
  • go install:工具安装、全局命令部署

3. 其他

  • go env 查看环境信息
    export GOOS=darwin (windows 中 set goos=linux) 可以将当前环境设置为linux 之后执行的打包命令,就可以生成能够在linux 环境中运行的程序
    go env GOOS GOARCH // 只查看环境GOOS GOARCH 这两个信息

以下是两张图片中提取的文字内容,为了方便阅读,我将它们按逻辑顺序整合在了一起:

4. 总结

核心工具链命令:

  1. go mod - 依赖管理
    • go mod init - 初始化项目
    • go mod tidy - 整理依赖
  2. go build - 编译构建
    • 生成可执行文件
    • 支持交叉编译
  3. go run - 快速运行
    • 开发调试使用
    • 快速验证代码
  4. go test - 测试框架
    • 单元测试
    • 基准测试
    • 代码覆盖率

开发工作流程:

  1. go mod init - 创建项目
  2. 编写代码和测试
  3. go test - 验证功能
  4. go run - 快速测试
  5. go build - 构建发布

练习

调试,分析工具(pprof,日志库)

1. 语法讲解

Go语言提供了强大的调试和性能分析工具链。

  • Delve调试器:Go语言的专用调试器,支持断点、单步执行、变量查看等
  • pprof:性能分析工具,支持CPU、内存、协程等分析 // 性能分析端点: http://localhost:8080/debug/pprof
  • 日志处理:标准库log和结构化日志库logrus等
  • 内置工具:race detector(竞态检测)、benchmark(基准测试)

2. 应用场景

  • Delve:复杂bug调试、并发问题分析、代码逻辑验证
  • pprof:性能瓶颈分析、内存泄漏排查、并发问题定位
  • 日志系统:程序运行监控、错误追踪、用户行为分析、审计日志
  • 竞态检测:并发代码验证、数据竞争问题排查

练习