diff --git a/note/资源/编程/Golang/常用命令.md b/note/资源/编程/Golang/常用命令.md index bfff9a4..b42c0b5 100644 --- a/note/资源/编程/Golang/常用命令.md +++ b/note/资源/编程/Golang/常用命令.md @@ -1,3 +1,48 @@ +## 依赖与模块管理 + +| 命令 | 作用 | 示例 | +| ----------------- | ---------------------------------------- | ---------------------------------------- | +| `go mod init` | 初始化一个新模块(生成 go.mod) | `go mod init myapp` | +| `go mod tidy` | 自动添加缺失的依赖、删除未使用的依赖 | `go mod tidy` | +| `go get` | 为当前模块添加/升级/降级依赖 | `go get github.com/gin-gonic/gin@v1.9.0` | +| `go mod download` | 预下载 go.mod 中声明的所有依赖到本地缓存 | `go mod download` | +| `go mod vendor` | 将依赖复制到 vendor 目录(离线构建用) | `go mod vendor` | +| `go list` | 列出包或模块信息 | `go list -m all`(查看所有依赖版本) | + +## 运行与安装 + +| 命令 | 作用 | 示例 | +| :----------- | :---------------------------------- | :----------------------------------- | +| `go run` | 编译并直接运行程序(适合调试) | `go run .` | +| `go install` | 编译并安装到 GOBIN 目录(全局可用) | `go install example.com/tool@latest` | + +## 代码质量与格式化 + +| 命令 | 作用 | 示例 | +| :------- | :--------------------------- | :------------- | +| `go fmt` | 自动格式化代码,符合官方风格 | `go fmt ./...` | +| `go vet` | 静态检查代码中潜在的错误 | `go vet ./...` | +| `go fix` | 自动把旧版 API 更新为新 API | `go fix ./...` | + +## 查看信息 + +| 命令 | 作用 | 示例 | +| :----------- | :--------------------- | :------------------------------------- | +| `go doc` | 查看包或函数的文档 | `go doc fmt.Println` | +| `go env` | 查看/修改 Go 环境配置 | `go env -w GOPROXY=https://goproxy.cn` | +| `go version` | 查看当前 Go 版本 | `go version` | +| `go help` | 查看某个命令的详细帮助 | `go help build` | + +## 其他进阶命令 + +| 命令 | 作用 | 说明 | +| :------------ | :---------------------------------------------- | :------------------------------------------------------- | +| `go clean` | 清除缓存和编译产物 | `go clean -cache`、`go clean -modcache` | +| `go generate` | 运行源代码中的 `//go:generate` 指令自动生成代码 | 常用于生成代码模板 | +| `go tool` | 调用 Go 自带工具 | `go tool pprof`(性能分析)、`go tool trace`(协程跟踪) | +| `go work` | 多模块工作区管理 | `go work init`、`go work use ./xxx` | +| `go bug` | 打开浏览器提交 bug 报告 | 会自动附带系统信息 | + ## 交叉编译 ### 基本用法 diff --git a/note/资源/编程/Golang/常用第三方库.md b/note/资源/编程/Golang/常用第三方库.md index 89a5482..654e8b0 100644 --- a/note/资源/编程/Golang/常用第三方库.md +++ b/note/资源/编程/Golang/常用第三方库.md @@ -115,3 +115,86 @@ func NewServiceContext(c config.Config) *ServiceContext { } ``` + + +### excelize + +读写Excel的Go库 + +[github](https://github.com/qax-os/excelize) + +#### 创建工作簿 + +```go + f := excelize.NewFile() + defer func() { + if err := f.Close(); err != nil { + fmt.Println(err) + } + }() + // 创建一个新的Sheet,返回的index为该工作簿的索引 + index, err := f.NewSheet("SheetName") + if err != nil { + return fmt.Errorf("创建Sheet失败: %w", err) + } +``` + +#### 打开文件 + +```go + f, err := excelize.OpenFile(filePath) + if err != nil { + return fmt.Errorf("打开 Excel失败: %w", err) + } + defer func() { + if err := f.Close(); err != nil { + fmt.Println(err) + } + }() +``` + +#### 写入cell值 + +```go + f.SetCellValue("SheetName", "B2", 100) +``` + +#### 设置工作簿默认活动工作表 + +```go +f.SetActiveSheet(index) +``` + +#### 创建或更新excel表 + +```go + if err := f.SaveAs("Book1.xlsx"); err != nil { + return fmt.Errorf("保存失败: %w", err) + } +``` + +#### 获取指定cell值 + +```go + cell, err := f.GetCellValue("Sheet1", "B2") + if err != nil { + return fmt.Errorf("读取cell失败: %w", err) + } + fmt.Println(cell) +``` + +#### 获取所有工作簿的cell值(二维数组) + +```go + rows, err := f.GetRows("Sheet1") + if err != nil { + return fmt.Errorf("读取失败: %w", err) + } + for _, row := range rows { + for _, colCell := range row { + fmt.Print(colCell, "\t") + } + fmt.Println() + } +``` + diff --git a/note/资源/编程/Golang/底层架构.md b/note/资源/编程/Golang/底层架构.md index 0e2ccf0..88c3e92 100644 --- a/note/资源/编程/Golang/底层架构.md +++ b/note/资源/编程/Golang/底层架构.md @@ -1,4 +1,4 @@ -Go 1.24 起,`map` 的底层实现从传统的 `hmap` + `bmap` 哈希表,彻底切换到了 Swiss Table(瑞士表) +> Go 1.24 起,`map` 的底层实现从传统的 `hmap` + `bmap` 哈希表,彻底切换到了 Swiss Table(瑞士表) ![Gemini_Generated_Image_jhqwi7jhqwi7jhqw](D:\zhangyuxin\code\lab\note\assets\golang-map[swiss table].png) diff --git a/note/随手记/go errors.md b/note/随手记/go errors.md new file mode 100644 index 0000000..b800a35 --- /dev/null +++ b/note/随手记/go errors.md @@ -0,0 +1,22 @@ +## `errors.AsType` + +> *用泛型把* `errors.As` *的“先声明变量再传指针”简化为“直接返回* `(E, bool)`*”,是* `errors.As` *的语法糖升级* + +**使用场景:** + +- 与 `errors.As` 完全相同(按类型提取错误),但写起来更简洁 +- 由于类型参数 `E` 必须是 `error` 接口的实现类型,**能在编译期避免 `errors.As` 那种“传错指针类型导致运行时 panic”的问题** + +```go +// 传统 errors.As:需要先声明变量 +var mysqlErr *mysql.MySQLError +if errors.As(err, &mysqlErr) { + return true, mysqlErr.Number +} + +// errors.AsType(Go 1.26+):无需预先声明变量 +if mysqlErr, ok := errors.AsType[*mysql.MySQLError](err); ok { + return true, mysqlErr.Number +} +``` + diff --git a/note/随手记/go操作excel.md b/note/随手记/go操作excel.md index e8fd7df..32eaa30 100644 --- a/note/随手记/go操作excel.md +++ b/note/随手记/go操作excel.md @@ -1,4 +1,4 @@ -## excelize库 +### excelize库 读写Excel的Go库 @@ -6,7 +6,7 @@ ## 基本用法 -### 创建工作簿 +#### 创建工作簿 ```go f := excelize.NewFile() @@ -22,7 +22,7 @@ } ``` -### 打开文件 +#### 打开文件 ```go f, err := excelize.OpenFile(filePath) @@ -36,19 +36,19 @@ }() ``` -### 写入cell值 +#### 写入cell值 ```go f.SetCellValue("SheetName", "B2", 100) ``` -### 设置工作簿默认活动工作表 +#### 设置工作簿默认活动工作表 ```go f.SetActiveSheet(index) ``` -### 创建或更新excel表 +#### 创建或更新excel表 ```go if err := f.SaveAs("Book1.xlsx"); err != nil { @@ -56,7 +56,7 @@ f.SetActiveSheet(index) } ``` -### 获取指定cell值 +#### 获取指定cell值 ```go cell, err := f.GetCellValue("Sheet1", "B2") @@ -66,7 +66,7 @@ f.SetActiveSheet(index) fmt.Println(cell) ``` -### 获取所有工作簿的cell值(二维数组) +#### 获取所有工作簿的cell值(二维数组) ```go rows, err := f.GetRows("Sheet1") diff --git a/note/随手记/mysql的字符集坑.md b/note/随手记/mysql的字符集坑.md new file mode 100644 index 0000000..ba5ed0f --- /dev/null +++ b/note/随手记/mysql的字符集坑.md @@ -0,0 +1,23 @@ +# MySQL 字符集的终极巨坑 —— `utf8` vs `utf8mb4` + +### 一句话总结 + +MySQL 中的 `utf8` 是个“假货”(最多只支持 3 字节),`utf8mb4` 才是真正的 UTF-8(支持 4 字节)。 + +### 为什么会有这个坑 + +- **历史遗留**:早期 MySQL 开发时,Unicode 字符确实只用 3 个字节就能存下。 +- **现象**:一旦用户输入 **Emoji 表情**(如 😀)或部分**生僻字**(如 𰻝),数据库会直接抛出错误:`Incorrect string value`。 + +### 📊 核心对比 + +| 字符集 | 真实身份 | 最大字节数 | 能否存 Emoji | 状态 | +| :------------ | :----------------- | :--------- | :----------- | :--------- | +| **`utf8`** | `utf8mb3` (阉割版) | 3 字节 | ❌ 报错 | ⚠️ 已废弃 | +| **`utf8mb4`** | 真正的 UTF-8 | 4 字节 | ✅ 随便存 | ✅ 推荐使用 | + +### 🛠️ 各版本现状与未来 + +- **MySQL 5.7 及以前**:默认字符集是 `latin1`,`utf8` 是重灾区。 +- **MySQL 8.0 及以后**:**默认字符集已改为 `utf8mb4`**(新项目安全系数提升)。 +- **官方态度**:目前 `utf8`(即 `utf8mb3`)已被标记为 Deprecated(废弃)。官方计划在**未来的某个大版本中彻底删除 `utf8mb3`**,并让 `utf8` 这个名字正式指向 `utf8mb4`。 \ No newline at end of file diff --git a/note/随手记/正则表达式.md b/note/随手记/正则表达式.md index e002956..3eb2a60 100644 --- a/note/随手记/正则表达式.md +++ b/note/随手记/正则表达式.md @@ -39,7 +39,7 @@ | `+` | 匹配前面的子表达式一次或多次。要匹配 `+` 字符本身,请使用 `\+`。 | | `.` | 匹配除换行符 `\n` 之外的任何单字符。要匹配 `.` 本身,请使用 `\.`。 | | `[` | 标记一个中括号表达式的开始。要匹配 `[`,请使用 `\[`。 | -| `?` | 匹配前面的子表达式零次或一次,或指明一个非贪婪限定符。要匹配 `?` 字符本身,请使用 `\?`。 | +| `?` | 匹配前面的子表达式零次或一次,等价于 `{0,1}`。要匹配 `?` 字符本身,请使用 `\?`。例如,`do(es)?` 可以匹配 "do" 和 "does",但不能匹配 "dog"。 | | `\` | 将下一个字符标记为特殊字符、原义字符、向后引用或八进制转义符。例如,`\\` 匹配 `\`。 | | `^` | 匹配输入字符串的开始位置。在方括号表达式中使用时,表示不接受方括号内的字符集合(取反)。要匹配 `^` 字符本身,请使用 `\^`。 | | `{` | 标记限定符表达式的开始。要匹配 `{`,请使用 `\{`。 | @@ -49,24 +49,16 @@ | 字符 | 描述 | | :------ | :----------------------------------------------------------- | -| `*` | 匹配前面的子表达式零次或多次。 | -| `+` | 匹配前面的子表达式一次或多次。 | -| `?` | 匹配前面的子表达式零次或一次,等价于 `{0,1}`。例如,`do(es)?` 可以匹配 "do" 和 "does",但不能匹配 "dog"。 | | `{n}` | n 是一个非负整数,匹配确定的 n 次。例如,`o{2}` 不能匹配 "Bob" 中的 o,但是能匹配 "food" 中的两个 o。 | | `{n,}` | n 是一个非负整数,至少匹配 n 次。例如,`o{2,}` 不能匹配 "Bob" 中的 o,但能匹配 "foooood" 中的所有 o。`o{1,}` 等价于 `o+`,`o{0,}` 等价于 `o*`。 | | `{n,m}` | m 和 n 均为非负整数,其中 n <= m。最少匹配 n 次且最多匹配 m 次。例如,`o{1,3}` 将匹配 "fooooood" 中的前三个 o。`o{0,1}` 等价于 `o?`。 | ## 常用正则表达式 -| 正则表达式 | 匹配内容 | -| -------------------------- | ---------- | -| `[\u4e00-\u9fa5]` | 中文字符 | -| `\d{3}-\d{8}|\d{4}-\{7,8}` | 国内手机号 | -| | | -| | | -| | | -| | | -| | | -| | | -| | | +| 正则表达式 | 匹配内容 | +| ------------------------------------------------ | ------------ | +| `[\u4e00-\u9fa5]` | 中文字符 | +| `^1[3-9]\d{9}$` | 国内手机号 | +| `[1-9]\d{5}(?!\d)` | 国内邮政编码 | +| `^(\d{6})(\d{4})(\d{2})(\d{2})(\d{3})([0-9]|X)$` | 18位身份证号 |