-
-
-
-
-
-
-
-
-
+
+
{{ router.currentRoute.value.params.blogName }}
+
+
+
+
\ No newline at end of file
+
diff --git a/public/_blogs/monorepo.md b/public/_blogs/monorepo.md
index 729bfa5..e09e9aa 100644
--- a/public/_blogs/monorepo.md
+++ b/public/_blogs/monorepo.md
@@ -1,2 +1,3 @@
# monorepo
+测试 github action
diff --git "a/public/_blogs/\346\216\230\351\207\221-\345\255\227\350\212\202go\350\257\255\350\250\200\345\255\246\344\271\240/\351\253\230\350\264\250\351\207\217\347\274\226\347\250\213\345\217\212\347\274\226\347\240\201\350\247\204\350\214\203.md" "b/public/_blogs/\346\216\230\351\207\221-\345\255\227\350\212\202go\350\257\255\350\250\200\345\255\246\344\271\240/\351\253\230\350\264\250\351\207\217\347\274\226\347\250\213\345\217\212\347\274\226\347\240\201\350\247\204\350\214\203.md"
index 8be97ce..a96f81e 100644
--- "a/public/_blogs/\346\216\230\351\207\221-\345\255\227\350\212\202go\350\257\255\350\250\200\345\255\246\344\271\240/\351\253\230\350\264\250\351\207\217\347\274\226\347\250\213\345\217\212\347\274\226\347\240\201\350\247\204\350\214\203.md"
+++ "b/public/_blogs/\346\216\230\351\207\221-\345\255\227\350\212\202go\350\257\255\350\250\200\345\255\246\344\271\240/\351\253\230\350\264\250\351\207\217\347\274\226\347\250\213\345\217\212\347\274\226\347\240\201\350\247\204\350\214\203.md"
@@ -1,86 +1,86 @@
# 高质量编程及编码规范
-* 如何编写简洁清晰的代码
-* 常用go语言程序优化手段
-* 熟悉go程序性能分析工具
-* 工程中性能优化的原则和流程
+- 如何编写简洁清晰的代码
+- 常用 go 语言程序优化手段
+- 熟悉 go 程序性能分析工具
+- 工程中性能优化的原则和流程
1. 高质量编程(高质量编程简介|编码规范|性能优化建议)
1. 什么是高质量
- * 高质量就是,编写的代码能够达到正确可靠、简介清晰的目标
- * 各种边界条件是否考虑完备
- * 异常情况处理,稳定性保证
- * 易读易维护
+ - 高质量就是,编写的代码能够达到正确可靠、简介清晰的目标
+ - 各种边界条件是否考虑完备
+ - 异常情况处理,稳定性保证
+ - 易读易维护
2. 编程原则
- * 简单性
- * 可读性
- * 生产力
+ - 简单性
+ - 可读性
+ - 生产力
3. 编码规范
- * 代码格式——推荐使用gofmt自动格式化代码 / goimports
- * 注释——公共符号始终要注释,解释代码作用,解释代码如何做的,解释代码实现的原因(提供额外上下文,外部因素),解释代码什么情况会出错(代码的限制条件),代码是最好的注释,注释应该提供代码未表达出的上下文信息
- * 命名规范
- * 简洁
- * 变量命名
- * 缩略词全大写,位于变量开头且不需要导出时,使用全小写
- * 例如使用ServeHTTP而不是ServeHttp
- * 使用XMLHTTPRequest或者xmlHTTPRequest
- * 变量距离其被使用的地方越远,则需要携带越多的上下文信息
- * 全局变量在其名字中需要更多上下文信息
- * 例子:i和index的作用域仅限于for循环内部时index的额外冗余没有意义
- * 函数命名
- * 函数名不携带包名的上下文信息,因为包名和函数名总是成对出现
- * 函数名尽量简短
- * 当名为foo的包某个函数返回类型为Foo时,可以省略类型信息而不导致歧义
- * 当名为foo的包某个函数返回类型为T时,可以在函数名中加入类型信息
- * package命名
- * 只由小写字母组成。不包括大写字母和下划线等字符
- * 简短并包含一定的上下文信息。例如schema、task等
- * 不要与标准库同名
- * 不适用常用变量名作为包名
- * 使用单数而不是复数
- * 谨慎使用缩写
- * 核心目标是降低阅读理解代码的成本
- * 重点考虑上下文信息,设计简洁清晰名称
- * 控制流程
- * 避免嵌套,保持正常流程
- * 尽量保持正常代码路径为最小缩进(有限处理错误/特殊情况,尽早返回或继续循环来减少嵌套)
- * 线性原理,避免复杂嵌套
- * 错误和异常处理
- * 简单错误
- * 仅出现一次,其他地方无需捕获
- * 优先使用errors.New来创建匿名变量来直接表示简单错误
- * 如果有格式化的需求,使用fmt.Errorf
- * 错误的Wrap和Unwrap
- * 错误的Wrap实际上是提供了一个error嵌套另一个error的能力,从而生成一个error的跟踪链
- * 在fmt.Errorf中使用:%w关键字来将一个错误关联至错误链中
- * 错误判定
- * 判定一个错误是否为特定错误,使用errors.Is
- * 不同于使用==,使用该方法可以判定错误链上的所有错误是否含有特定的错误
- * 在错误链上获取特定种类的错误,使用errors.As
- * panic
- * 不建议在业务代码中使用panic
- * 调用函数不包含recover会造成程序崩溃
- * 若问题可以被屏蔽或解决,建议使用error代替panic
- * 当程序启动阶段发生不可逆转的错误时,可以在init或main函数中使用panic
- * recover
- * recover只能在被defer的函数中使用
- * 嵌套无法生效
- * 只在当前goroutine生效
- * defer的语句总是先进后出
- * 如果需要更多上下文信息,可以在recover后在log中记录当前的调用栈
- * 总结:
- * error尽可能提供简明的上下文信息链,方便定位问题
- * panic用于真正异常的情况
- * recover生效范围,在当前goroutine的被defer的函数中生效
+ - 代码格式——推荐使用 gofmt 自动格式化代码 / goimports
+ - 注释——公共符号始终要注释,解释代码作用,解释代码如何做的,解释代码实现的原因(提供额外上下文,外部因素),解释代码什么情况会出错(代码的限制条件),代码是最好的注释,注释应该提供代码未表达出的上下文信息
+ - 命名规范
+ - 简洁
+ - 变量命名
+ - 缩略词全大写,位于变量开头且不需要导出时,使用全小写
+ - 例如使用 ServeHTTP 而不是 ServeHttp
+ - 使用 XMLHTTPRequest 或者 xmlHTTPRequest
+ - 变量距离其被使用的地方越远,则需要携带越多的上下文信息
+ - 全局变量在其名字中需要更多上下文信息
+ - 例子:i 和 index 的作用域仅限于 for 循环内部时 index 的额外冗余没有意义
+ - 函数命名
+ - 函数名不携带包名的上下文信息,因为包名和函数名总是成对出现
+ - 函数名尽量简短
+ - 当名为 foo 的包某个函数返回类型为 Foo 时,可以省略类型信息而不导致歧义
+ - 当名为 foo 的包某个函数返回类型为 T 时,可以在函数名中加入类型信息
+ - package 命名
+ - 只由小写字母组成。不包括大写字母和下划线等字符
+ - 简短并包含一定的上下文信息。例如 schema、task 等
+ - 不要与标准库同名
+ - 不适用常用变量名作为包名
+ - 使用单数而不是复数
+ - 谨慎使用缩写
+ - 核心目标是降低阅读理解代码的成本
+ - 重点考虑上下文信息,设计简洁清晰名称
+ - 控制流程
+ - 避免嵌套,保持正常流程
+ - 尽量保持正常代码路径为最小缩进(有限处理错误/特殊情况,尽早返回或继续循环来减少嵌套)
+ - 线性原理,避免复杂嵌套
+ - 错误和异常处理
+ - 简单错误
+ - 仅出现一次,其他地方无需捕获
+ - 优先使用 errors.New 来创建匿名变量来直接表示简单错误
+ - 如果有格式化的需求,使用 fmt.Errorf
+ - 错误的 Wrap 和 Unwrap
+ - 错误的 Wrap 实际上是提供了一个 error 嵌套另一个 error 的能力,从而生成一个 error 的跟踪链
+ - 在 fmt.Errorf 中使用:%w 关键字来将一个错误关联至错误链中
+ - 错误判定
+ - 判定一个错误是否为特定错误,使用 errors.Is
+ - 不同于使用==,使用该方法可以判定错误链上的所有错误是否含有特定的错误
+ - 在错误链上获取特定种类的错误,使用 errors.As
+ - panic
+ - 不建议在业务代码中使用 panic
+ - 调用函数不包含 recover 会造成程序崩溃
+ - 若问题可以被屏蔽或解决,建议使用 error 代替 panic
+ - 当程序启动阶段发生不可逆转的错误时,可以在 init 或 main 函数中使用 panic
+ - recover
+ - recover 只能在被 defer 的函数中使用
+ - 嵌套无法生效
+ - 只在当前 goroutine 生效
+ - defer 的语句总是先进后出
+ - 如果需要更多上下文信息,可以在 recover 后在 log 中记录当前的调用栈
+ - 总结:
+ - error 尽可能提供简明的上下文信息链,方便定位问题
+ - panic 用于真正异常的情况
+ - recover 生效范围,在当前 goroutine 的被 defer 的函数中生效
-2. 性能调优实战(性能调优简介|性能分析工具pprof实战|性能调优案例)
+2. 性能调优实战(性能调优简介|性能分析工具 pprof 实战|性能调优案例)
- * 性能优化前提是满足正确可靠、简介清晰等质量因素
- * 性能优化是综合评估
+ - 性能优化前提是满足正确可靠、简介清晰等质量因素
+ - 性能优化是综合评估
1. 如何使用
- * 性能表现需要实际数据衡量
- * Go语言提供了基准性能测试的benchmark工具
- 2. slice预分配内存
- * 尽可能在使用make()初始化切片时提供容量信息
\ No newline at end of file
+ - 性能表现需要实际数据衡量
+ - Go 语言提供了基准性能测试的 benchmark 工具
+ 2. slice 预分配内存
+ - 尽可能在使用 make()初始化切片时提供容量信息
diff --git a/server/api/blogsTree.js b/server/api/blogsTree.js
index fab45a1..0133c54 100644
--- a/server/api/blogsTree.js
+++ b/server/api/blogsTree.js
@@ -1,13 +1,13 @@
import { getAllfiles, blogsTreeHandler } from "../handler/blogsTree";
-export default defineEventHandler(even => {
- return new Promise((resolve, reject) => {
- const blogsTree = [];
- try {
- getAllfiles('public/_blogs', blogsTree);
- blogsTreeHandler(blogsTree);
- resolve(blogsTree);
- } catch (error) {
- reject(error);
- }
- });
-});
\ No newline at end of file
+export default defineEventHandler((even) => {
+ return new Promise((resolve, reject) => {
+ const blogsTree = [];
+ try {
+ getAllfiles("public/_blogs", blogsTree);
+ blogsTreeHandler(blogsTree);
+ resolve(blogsTree);
+ } catch (error) {
+ reject(error);
+ }
+ });
+});
diff --git a/server/api/readblog.js b/server/api/readblog.js
index c2d76ef..32660af 100644
--- a/server/api/readblog.js
+++ b/server/api/readblog.js
@@ -1,13 +1,13 @@
-import fs from 'fs';
-export default defineEventHandler(event => {
- return new Promise((resolve, reject) => {
- const query = getQuery(event);
- const path = query.path;
- fs.readFile(`${path}`, 'utf-8', (err, data) => {
- if (err) {
- reject(err);
- }
- resolve(data);
- });
+import fs from "fs";
+export default defineEventHandler((event) => {
+ return new Promise((resolve, reject) => {
+ const query = getQuery(event);
+ const path = query.path;
+ fs.readFile(`${path}`, "utf-8", (err, data) => {
+ if (err) {
+ reject(err);
+ }
+ resolve(data);
});
-});
\ No newline at end of file
+ });
+});
diff --git a/server/handler/blogsTree.js b/server/handler/blogsTree.js
index d314cc9..06b65e0 100644
--- a/server/handler/blogsTree.js
+++ b/server/handler/blogsTree.js
@@ -1,36 +1,43 @@
-import fs from 'fs';
+import fs from "fs";
/**
* @description 读取目录下所有目录文件 返回数组
* @param path 文件目录
- * @returns
+ * @returns
*/
-function getfiles(path) { //读取目录下所有目录文件 返回数组
- const dirfiles = fs.readdirSync(path, { encoding: 'utf8', withFileTypes: true });
- return dirfiles;
+function getfiles(path) {
+ //读取目录下所有目录文件 返回数组
+ const dirfiles = fs.readdirSync(path, {
+ encoding: "utf-8",
+ withFileTypes: true,
+ });
+ console.log(dirfiles);
+ return dirfiles;
}
// const files = getfiles('../blogs/');
// console.log(files);
/**
* @description 判断是否是文件 Boolean
- * @param filepath
- * @returns
+ * @param filepath
+ * @returns
*/
-function isFile(filepath) { //判断是否是文件 Boolean
- let stat = fs.statSync(filepath);
- return stat.isFile();
+function isFile(filepath) {
+ //判断是否是文件 Boolean
+ let stat = fs.statSync(filepath);
+ return stat.isFile();
}
// const type = isFile('../blogs/blo.md');
// console.log(type);
/**
* @description 判断是否是文件夹 Boolean
- * @param filepath
- * @returns
+ * @param filepath
+ * @returns
*/
-function isDir(filepath) { //判断是否是文件夹 Boolean
- let stat = fs.statSync(filepath);
- return stat.isDirectory();
+function isDir(filepath) {
+ //判断是否是文件夹 Boolean
+ let stat = fs.statSync(filepath);
+ return stat.isDirectory();
}
//递归遍历所有文件夹和文件
@@ -40,39 +47,45 @@ function isDir(filepath) { //判断是否是文件夹 Boolean
* @param path 路径
* @param arr 将结果存储到该数组中
*/
-function getAllfiles(path, arr) { // 结果将存储到arr数组中
- const filesArr = getfiles(path); // 获取目录下所有文件
- if (path.slice(-1) == '/') {
- path = path.slice(0, -1);
+function getAllfiles(path, arr) {
+ // 结果将存储到arr数组中
+ const filesArr = getfiles(path); // 获取目录下所有文件
+ if (path.slice(-1) == "/") {
+ path = path.slice(0, -1);
+ }
+ filesArr.forEach((item) => {
+ const fileName = item.name;
+ const filePath = `${path}/${fileName}`;
+ if (isDir(filePath)) {
+ //如果是文件夹
+ const itemFileArr = [];
+ getAllfiles(filePath, itemFileArr);
+ const dir = {
+ name: fileName,
+ type: "dir",
+ dirPath: `${filePath}/`,
+ children: itemFileArr,
+ };
+ arr.push(dir);
+ } else if (isFile(filePath)) {
+ // 如果是文件
+ arr.push({ name: fileName, type: "file", path: filePath });
}
- filesArr.forEach(item => {
- const fileName = item.name;
- const filePath = `${path}/${fileName}`;
- if (isDir(filePath)) { //如果是文件夹
- const itemFileArr = [];
- getAllfiles(filePath, itemFileArr);
- const dir = { name: fileName, type: 'dir', dirPath: `${filePath}/`, children: itemFileArr };
- arr.push(dir);
- } else if (isFile(filePath)) { // 如果是文件
- arr.push({ name: fileName, type: 'file', path: filePath });
- }
- });
+ });
}
// const arr = [];
// getAllfiles('../blogs', arr);
// console.log(arr);
const blogsTreeHandler = (blogsTree) => {
- let obj;
- for (const key in blogsTree) {
- if (blogsTree[key].name == 'README.md') {
- obj = { ...blogsTree[key] };
- blogsTree.splice(key, 1);
- blogsTree.unshift(obj);
- return;
- }
+ let obj;
+ for (const key in blogsTree) {
+ if (blogsTree[key].name == "README.md") {
+ obj = { ...blogsTree[key] };
+ blogsTree.splice(key, 1);
+ blogsTree.unshift(obj);
+ return;
}
+ }
};
-export {
- getAllfiles, blogsTreeHandler
-};
+export { getAllfiles, blogsTreeHandler };