ccg-workflow 1.8.2 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.mjs +1 -1
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +1 -1
- package/dist/shared/{ccg-workflow.B1RHp04H.mjs → ccg-workflow.iK6lgCG3.mjs} +204 -6
- package/package.json +1 -1
- package/templates/commands/agents/team-architect.md +97 -0
- package/templates/commands/agents/team-qa.md +121 -0
- package/templates/commands/agents/team-reviewer.md +112 -0
- package/templates/output-styles/abyss-command.md +56 -0
- package/templates/output-styles/abyss-concise.md +89 -0
- package/templates/output-styles/abyss-ritual.md +70 -0
- package/templates/rules/ccg-skill-routing.md +83 -0
- package/templates/skills/domains/ai/SKILL.md +34 -0
- package/templates/skills/domains/ai/agent-dev.md +242 -0
- package/templates/skills/domains/ai/llm-security.md +288 -0
- package/templates/skills/domains/ai/prompt-and-eval.md +279 -0
- package/templates/skills/domains/ai/rag-system.md +542 -0
- package/templates/skills/domains/architecture/SKILL.md +42 -0
- package/templates/skills/domains/architecture/api-design.md +225 -0
- package/templates/skills/domains/architecture/caching.md +299 -0
- package/templates/skills/domains/architecture/cloud-native.md +285 -0
- package/templates/skills/domains/architecture/message-queue.md +329 -0
- package/templates/skills/domains/architecture/security-arch.md +297 -0
- package/templates/skills/domains/data-engineering/SKILL.md +207 -0
- package/templates/skills/domains/development/SKILL.md +46 -0
- package/templates/skills/domains/development/cpp.md +246 -0
- package/templates/skills/domains/development/go.md +323 -0
- package/templates/skills/domains/development/java.md +277 -0
- package/templates/skills/domains/development/python.md +288 -0
- package/templates/skills/domains/development/rust.md +313 -0
- package/templates/skills/domains/development/shell.md +313 -0
- package/templates/skills/domains/development/typescript.md +277 -0
- package/templates/skills/domains/devops/SKILL.md +39 -0
- package/templates/skills/domains/devops/cost-optimization.md +272 -0
- package/templates/skills/domains/devops/database.md +217 -0
- package/templates/skills/domains/devops/devsecops.md +198 -0
- package/templates/skills/domains/devops/git-workflow.md +181 -0
- package/templates/skills/domains/devops/observability.md +280 -0
- package/templates/skills/domains/devops/performance.md +336 -0
- package/templates/skills/domains/devops/testing.md +283 -0
- package/templates/skills/domains/frontend-design/SKILL.md +242 -0
- package/templates/skills/domains/frontend-design/agents/openai.yaml +4 -0
- package/templates/skills/domains/frontend-design/claymorphism/SKILL.md +119 -0
- package/templates/skills/domains/frontend-design/claymorphism/references/tokens.css +52 -0
- package/templates/skills/domains/frontend-design/component-patterns.md +202 -0
- package/templates/skills/domains/frontend-design/engineering.md +287 -0
- package/templates/skills/domains/frontend-design/glassmorphism/SKILL.md +140 -0
- package/templates/skills/domains/frontend-design/glassmorphism/references/tokens.css +32 -0
- package/templates/skills/domains/frontend-design/liquid-glass/SKILL.md +137 -0
- package/templates/skills/domains/frontend-design/liquid-glass/references/tokens.css +81 -0
- package/templates/skills/domains/frontend-design/neubrutalism/SKILL.md +143 -0
- package/templates/skills/domains/frontend-design/neubrutalism/references/tokens.css +44 -0
- package/templates/skills/domains/frontend-design/reference/color-and-contrast.md +132 -0
- package/templates/skills/domains/frontend-design/reference/interaction-design.md +195 -0
- package/templates/skills/domains/frontend-design/reference/motion-design.md +99 -0
- package/templates/skills/domains/frontend-design/reference/responsive-design.md +114 -0
- package/templates/skills/domains/frontend-design/reference/spatial-design.md +100 -0
- package/templates/skills/domains/frontend-design/reference/typography.md +133 -0
- package/templates/skills/domains/frontend-design/reference/ux-writing.md +107 -0
- package/templates/skills/domains/frontend-design/state-management.md +680 -0
- package/templates/skills/domains/frontend-design/ui-aesthetics.md +110 -0
- package/templates/skills/domains/frontend-design/ux-principles.md +156 -0
- package/templates/skills/domains/infrastructure/SKILL.md +200 -0
- package/templates/skills/domains/mobile/SKILL.md +224 -0
- package/templates/skills/domains/orchestration/SKILL.md +29 -0
- package/templates/skills/domains/orchestration/multi-agent.md +263 -0
- package/templates/skills/domains/security/SKILL.md +72 -0
- package/templates/skills/domains/security/blue-team.md +436 -0
- package/templates/skills/domains/security/code-audit.md +265 -0
- package/templates/skills/domains/security/pentest.md +226 -0
- package/templates/skills/domains/security/red-team.md +374 -0
- package/templates/skills/domains/security/threat-intel.md +372 -0
- package/templates/skills/domains/security/vuln-research.md +369 -0
- package/templates/skills/impeccable/adapt/SKILL.md +199 -0
- package/templates/skills/impeccable/animate/SKILL.md +174 -0
- package/templates/skills/impeccable/arrange/SKILL.md +124 -0
- package/templates/skills/impeccable/audit/SKILL.md +147 -0
- package/templates/skills/impeccable/bolder/SKILL.md +116 -0
- package/templates/skills/impeccable/clarify/SKILL.md +183 -0
- package/templates/skills/impeccable/colorize/SKILL.md +142 -0
- package/templates/skills/impeccable/critique/SKILL.md +201 -0
- package/templates/skills/impeccable/critique/reference/cognitive-load.md +106 -0
- package/templates/skills/impeccable/critique/reference/heuristics-scoring.md +234 -0
- package/templates/skills/impeccable/critique/reference/personas.md +178 -0
- package/templates/skills/impeccable/delight/SKILL.md +303 -0
- package/templates/skills/impeccable/distill/SKILL.md +121 -0
- package/templates/skills/impeccable/extract/SKILL.md +92 -0
- package/templates/skills/impeccable/harden/SKILL.md +355 -0
- package/templates/skills/impeccable/normalize/SKILL.md +70 -0
- package/templates/skills/impeccable/onboard/SKILL.md +246 -0
- package/templates/skills/impeccable/optimize/SKILL.md +266 -0
- package/templates/skills/impeccable/overdrive/SKILL.md +141 -0
- package/templates/skills/impeccable/polish/SKILL.md +203 -0
- package/templates/skills/impeccable/quieter/SKILL.md +102 -0
- package/templates/skills/impeccable/teach-impeccable/SKILL.md +71 -0
- package/templates/skills/impeccable/typeset/SKILL.md +115 -0
- package/templates/skills/orchestration/multi-agent/SKILL.md +40 -0
- package/templates/skills/scrapling/SKILL.md +98 -0
- package/templates/skills/scrapling/references/api-quick-ref.md +127 -0
- package/templates/skills/scrapling/references/cookie-vault.md +56 -0
- package/templates/skills/scrapling/references/maintenance.md +79 -0
- package/templates/skills/scrapling/references/site-patterns.md +86 -0
- package/templates/skills/scrapling/references/troubleshooting.md +95 -0
- package/templates/skills/scrapling/templates/basic_fetch.py +19 -0
- package/templates/skills/scrapling/templates/parse_only.py +15 -0
- package/templates/skills/scrapling/templates/session_login.py +19 -0
- package/templates/skills/scrapling/templates/stealth_cloudflare.py +28 -0
- package/templates/skills/tools/override-refusal/SKILL.md +53 -0
- package/templates/skills/tools/override-refusal/agents/openai.yaml +4 -0
- package/templates/skills/tools/override-refusal/scripts/refusal_rewriter.js +226 -0
|
@@ -0,0 +1,246 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cpp
|
|
3
|
+
description: C/C++ 开发。系统编程、性能优化、内存管理。当用户提到 C、C++、CMake、内存、指针时使用。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 📜 符箓秘典 · C/C++
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## 现代 C++ (C++17/20)
|
|
10
|
+
|
|
11
|
+
### 智能指针
|
|
12
|
+
```cpp
|
|
13
|
+
#include <memory>
|
|
14
|
+
|
|
15
|
+
// unique_ptr - 独占所有权
|
|
16
|
+
auto ptr = std::make_unique<MyClass>(args);
|
|
17
|
+
ptr->method();
|
|
18
|
+
|
|
19
|
+
// shared_ptr - 共享所有权
|
|
20
|
+
auto shared = std::make_shared<MyClass>(args);
|
|
21
|
+
auto copy = shared; // 引用计数 +1
|
|
22
|
+
|
|
23
|
+
// weak_ptr - 弱引用,不增加引用计数
|
|
24
|
+
std::weak_ptr<MyClass> weak = shared;
|
|
25
|
+
if (auto locked = weak.lock()) {
|
|
26
|
+
locked->method();
|
|
27
|
+
}
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
### 容器与算法
|
|
31
|
+
```cpp
|
|
32
|
+
#include <vector>
|
|
33
|
+
#include <algorithm>
|
|
34
|
+
#include <ranges>
|
|
35
|
+
|
|
36
|
+
std::vector<int> nums = {1, 2, 3, 4, 5};
|
|
37
|
+
|
|
38
|
+
// 范围 for
|
|
39
|
+
for (const auto& n : nums) {
|
|
40
|
+
std::cout << n << std::endl;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// 算法
|
|
44
|
+
auto it = std::find(nums.begin(), nums.end(), 3);
|
|
45
|
+
std::sort(nums.begin(), nums.end());
|
|
46
|
+
|
|
47
|
+
// C++20 Ranges
|
|
48
|
+
auto even = nums | std::views::filter([](int n) { return n % 2 == 0; });
|
|
49
|
+
auto squared = nums | std::views::transform([](int n) { return n * n; });
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### Lambda 表达式
|
|
53
|
+
```cpp
|
|
54
|
+
// 基础 lambda
|
|
55
|
+
auto add = [](int a, int b) { return a + b; };
|
|
56
|
+
|
|
57
|
+
// 捕获
|
|
58
|
+
int x = 10;
|
|
59
|
+
auto capture_val = [x]() { return x; }; // 值捕获
|
|
60
|
+
auto capture_ref = [&x]() { return x; }; // 引用捕获
|
|
61
|
+
auto capture_all = [=]() { return x; }; // 全部值捕获
|
|
62
|
+
auto capture_all_ref = [&]() { return x; }; // 全部引用捕获
|
|
63
|
+
|
|
64
|
+
// 泛型 lambda (C++14)
|
|
65
|
+
auto generic = [](auto a, auto b) { return a + b; };
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### 并发编程
|
|
69
|
+
```cpp
|
|
70
|
+
#include <thread>
|
|
71
|
+
#include <mutex>
|
|
72
|
+
#include <future>
|
|
73
|
+
|
|
74
|
+
// 线程
|
|
75
|
+
std::thread t([]() {
|
|
76
|
+
std::cout << "Hello from thread" << std::endl;
|
|
77
|
+
});
|
|
78
|
+
t.join();
|
|
79
|
+
|
|
80
|
+
// 互斥锁
|
|
81
|
+
std::mutex mtx;
|
|
82
|
+
{
|
|
83
|
+
std::lock_guard<std::mutex> lock(mtx);
|
|
84
|
+
// 临界区
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// async/future
|
|
88
|
+
auto future = std::async(std::launch::async, []() {
|
|
89
|
+
return compute_result();
|
|
90
|
+
});
|
|
91
|
+
auto result = future.get();
|
|
92
|
+
|
|
93
|
+
// 条件变量
|
|
94
|
+
std::condition_variable cv;
|
|
95
|
+
std::unique_lock<std::mutex> lock(mtx);
|
|
96
|
+
cv.wait(lock, []() { return ready; });
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
## 内存管理
|
|
100
|
+
|
|
101
|
+
### RAII 模式
|
|
102
|
+
```cpp
|
|
103
|
+
class FileHandle {
|
|
104
|
+
public:
|
|
105
|
+
FileHandle(const char* path) : file(fopen(path, "r")) {
|
|
106
|
+
if (!file) throw std::runtime_error("Failed to open file");
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
~FileHandle() {
|
|
110
|
+
if (file) fclose(file);
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
// 禁止拷贝
|
|
114
|
+
FileHandle(const FileHandle&) = delete;
|
|
115
|
+
FileHandle& operator=(const FileHandle&) = delete;
|
|
116
|
+
|
|
117
|
+
// 允许移动
|
|
118
|
+
FileHandle(FileHandle&& other) noexcept : file(other.file) {
|
|
119
|
+
other.file = nullptr;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
private:
|
|
123
|
+
FILE* file;
|
|
124
|
+
};
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### 内存安全检查
|
|
128
|
+
```bash
|
|
129
|
+
# AddressSanitizer
|
|
130
|
+
g++ -fsanitize=address -g main.cpp -o main
|
|
131
|
+
./main
|
|
132
|
+
|
|
133
|
+
# Valgrind
|
|
134
|
+
valgrind --leak-check=full ./main
|
|
135
|
+
|
|
136
|
+
# 静态分析
|
|
137
|
+
clang-tidy main.cpp
|
|
138
|
+
cppcheck main.cpp
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
## CMake
|
|
142
|
+
|
|
143
|
+
### CMakeLists.txt
|
|
144
|
+
```cmake
|
|
145
|
+
cmake_minimum_required(VERSION 3.16)
|
|
146
|
+
project(MyProject VERSION 1.0.0 LANGUAGES CXX)
|
|
147
|
+
|
|
148
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
149
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
150
|
+
|
|
151
|
+
# 添加可执行文件
|
|
152
|
+
add_executable(myapp
|
|
153
|
+
src/main.cpp
|
|
154
|
+
src/utils.cpp
|
|
155
|
+
)
|
|
156
|
+
|
|
157
|
+
# 添加库
|
|
158
|
+
add_library(mylib STATIC
|
|
159
|
+
src/lib.cpp
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
# 链接库
|
|
163
|
+
target_link_libraries(myapp PRIVATE mylib)
|
|
164
|
+
|
|
165
|
+
# 包含目录
|
|
166
|
+
target_include_directories(myapp PRIVATE ${CMAKE_SOURCE_DIR}/include)
|
|
167
|
+
|
|
168
|
+
# 查找外部库
|
|
169
|
+
find_package(Threads REQUIRED)
|
|
170
|
+
target_link_libraries(myapp PRIVATE Threads::Threads)
|
|
171
|
+
|
|
172
|
+
# 测试
|
|
173
|
+
enable_testing()
|
|
174
|
+
add_executable(tests tests/test_main.cpp)
|
|
175
|
+
add_test(NAME MyTests COMMAND tests)
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### 构建
|
|
179
|
+
```bash
|
|
180
|
+
mkdir build && cd build
|
|
181
|
+
cmake ..
|
|
182
|
+
cmake --build .
|
|
183
|
+
ctest # 运行测试
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## 测试
|
|
187
|
+
|
|
188
|
+
### Google Test
|
|
189
|
+
```cpp
|
|
190
|
+
#include <gtest/gtest.h>
|
|
191
|
+
|
|
192
|
+
TEST(MathTest, Add) {
|
|
193
|
+
EXPECT_EQ(add(1, 2), 3);
|
|
194
|
+
EXPECT_EQ(add(-1, 1), 0);
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
TEST(MathTest, Divide) {
|
|
198
|
+
EXPECT_DOUBLE_EQ(divide(10, 2), 5.0);
|
|
199
|
+
EXPECT_THROW(divide(1, 0), std::invalid_argument);
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// Fixture
|
|
203
|
+
class UserTest : public ::testing::Test {
|
|
204
|
+
protected:
|
|
205
|
+
void SetUp() override {
|
|
206
|
+
user = std::make_unique<User>("Alice");
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
std::unique_ptr<User> user;
|
|
210
|
+
};
|
|
211
|
+
|
|
212
|
+
TEST_F(UserTest, GetName) {
|
|
213
|
+
EXPECT_EQ(user->getName(), "Alice");
|
|
214
|
+
}
|
|
215
|
+
```
|
|
216
|
+
|
|
217
|
+
## 项目结构
|
|
218
|
+
|
|
219
|
+
```
|
|
220
|
+
myproject/
|
|
221
|
+
├── CMakeLists.txt
|
|
222
|
+
├── include/
|
|
223
|
+
│ └── myproject/
|
|
224
|
+
│ ├── utils.h
|
|
225
|
+
│ └── types.h
|
|
226
|
+
├── src/
|
|
227
|
+
│ ├── main.cpp
|
|
228
|
+
│ └── utils.cpp
|
|
229
|
+
├── tests/
|
|
230
|
+
│ └── test_main.cpp
|
|
231
|
+
└── build/
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
## 常用库
|
|
235
|
+
|
|
236
|
+
| 库 | 用途 |
|
|
237
|
+
|---|------|
|
|
238
|
+
| Boost | 通用库集合 |
|
|
239
|
+
| fmt | 格式化输出 |
|
|
240
|
+
| spdlog | 日志 |
|
|
241
|
+
| nlohmann/json | JSON |
|
|
242
|
+
| Catch2/GTest | 测试 |
|
|
243
|
+
| OpenSSL | 加密 |
|
|
244
|
+
|
|
245
|
+
---
|
|
246
|
+
|
|
@@ -0,0 +1,323 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: go
|
|
3
|
+
description: Go 开发。高并发、微服务、云原生、CLI工具。当用户提到 Go、Golang、Gin、Echo、goroutine 时使用。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 📜 符箓秘典 · Go
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
## Web 框架
|
|
10
|
+
|
|
11
|
+
### Gin
|
|
12
|
+
```go
|
|
13
|
+
package main
|
|
14
|
+
|
|
15
|
+
import (
|
|
16
|
+
"net/http"
|
|
17
|
+
"github.com/gin-gonic/gin"
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
type User struct {
|
|
21
|
+
ID int `json:"id"`
|
|
22
|
+
Name string `json:"name" binding:"required"`
|
|
23
|
+
Email string `json:"email" binding:"required,email"`
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
func main() {
|
|
27
|
+
r := gin.Default()
|
|
28
|
+
|
|
29
|
+
// 中间件
|
|
30
|
+
r.Use(gin.Logger())
|
|
31
|
+
r.Use(gin.Recovery())
|
|
32
|
+
|
|
33
|
+
// 路由组
|
|
34
|
+
api := r.Group("/api")
|
|
35
|
+
{
|
|
36
|
+
api.GET("/users/:id", getUser)
|
|
37
|
+
api.POST("/users", createUser)
|
|
38
|
+
api.PUT("/users/:id", updateUser)
|
|
39
|
+
api.DELETE("/users/:id", deleteUser)
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
r.Run(":8080")
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
func getUser(c *gin.Context) {
|
|
46
|
+
id := c.Param("id")
|
|
47
|
+
c.JSON(http.StatusOK, gin.H{"id": id})
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
func createUser(c *gin.Context) {
|
|
51
|
+
var user User
|
|
52
|
+
if err := c.ShouldBindJSON(&user); err != nil {
|
|
53
|
+
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
|
|
54
|
+
return
|
|
55
|
+
}
|
|
56
|
+
c.JSON(http.StatusCreated, user)
|
|
57
|
+
}
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
### Echo
|
|
61
|
+
```go
|
|
62
|
+
package main
|
|
63
|
+
|
|
64
|
+
import (
|
|
65
|
+
"net/http"
|
|
66
|
+
"github.com/labstack/echo/v4"
|
|
67
|
+
"github.com/labstack/echo/v4/middleware"
|
|
68
|
+
)
|
|
69
|
+
|
|
70
|
+
func main() {
|
|
71
|
+
e := echo.New()
|
|
72
|
+
|
|
73
|
+
e.Use(middleware.Logger())
|
|
74
|
+
e.Use(middleware.Recover())
|
|
75
|
+
|
|
76
|
+
e.GET("/users/:id", getUser)
|
|
77
|
+
e.POST("/users", createUser)
|
|
78
|
+
|
|
79
|
+
e.Logger.Fatal(e.Start(":8080"))
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
func getUser(c echo.Context) error {
|
|
83
|
+
id := c.Param("id")
|
|
84
|
+
return c.JSON(http.StatusOK, map[string]string{"id": id})
|
|
85
|
+
}
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## 并发编程
|
|
89
|
+
|
|
90
|
+
### Goroutine & Channel
|
|
91
|
+
```go
|
|
92
|
+
package main
|
|
93
|
+
|
|
94
|
+
import (
|
|
95
|
+
"fmt"
|
|
96
|
+
"sync"
|
|
97
|
+
)
|
|
98
|
+
|
|
99
|
+
// 基础并发
|
|
100
|
+
func worker(id int, jobs <-chan int, results chan<- int) {
|
|
101
|
+
for j := range jobs {
|
|
102
|
+
results <- j * 2
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
func main() {
|
|
107
|
+
jobs := make(chan int, 100)
|
|
108
|
+
results := make(chan int, 100)
|
|
109
|
+
|
|
110
|
+
// 启动 worker
|
|
111
|
+
for w := 1; w <= 3; w++ {
|
|
112
|
+
go worker(w, jobs, results)
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 发送任务
|
|
116
|
+
for j := 1; j <= 9; j++ {
|
|
117
|
+
jobs <- j
|
|
118
|
+
}
|
|
119
|
+
close(jobs)
|
|
120
|
+
|
|
121
|
+
// 收集结果
|
|
122
|
+
for a := 1; a <= 9; a++ {
|
|
123
|
+
<-results
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
// WaitGroup
|
|
128
|
+
func parallelFetch(urls []string) []string {
|
|
129
|
+
var wg sync.WaitGroup
|
|
130
|
+
results := make([]string, len(urls))
|
|
131
|
+
|
|
132
|
+
for i, url := range urls {
|
|
133
|
+
wg.Add(1)
|
|
134
|
+
go func(i int, url string) {
|
|
135
|
+
defer wg.Done()
|
|
136
|
+
results[i] = fetch(url)
|
|
137
|
+
}(i, url)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
wg.Wait()
|
|
141
|
+
return results
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Context 控制
|
|
145
|
+
func fetchWithTimeout(ctx context.Context, url string) (string, error) {
|
|
146
|
+
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
|
|
147
|
+
defer cancel()
|
|
148
|
+
|
|
149
|
+
req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
|
|
150
|
+
resp, err := http.DefaultClient.Do(req)
|
|
151
|
+
if err != nil {
|
|
152
|
+
return "", err
|
|
153
|
+
}
|
|
154
|
+
defer resp.Body.Close()
|
|
155
|
+
|
|
156
|
+
body, _ := io.ReadAll(resp.Body)
|
|
157
|
+
return string(body), nil
|
|
158
|
+
}
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
## 错误处理
|
|
162
|
+
|
|
163
|
+
```go
|
|
164
|
+
package main
|
|
165
|
+
|
|
166
|
+
import (
|
|
167
|
+
"errors"
|
|
168
|
+
"fmt"
|
|
169
|
+
)
|
|
170
|
+
|
|
171
|
+
// 自定义错误
|
|
172
|
+
var ErrNotFound = errors.New("not found")
|
|
173
|
+
|
|
174
|
+
type ValidationError struct {
|
|
175
|
+
Field string
|
|
176
|
+
Message string
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
func (e *ValidationError) Error() string {
|
|
180
|
+
return fmt.Sprintf("%s: %s", e.Field, e.Message)
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// 错误包装
|
|
184
|
+
func getUser(id int) (*User, error) {
|
|
185
|
+
user, err := db.FindUser(id)
|
|
186
|
+
if err != nil {
|
|
187
|
+
return nil, fmt.Errorf("getUser(%d): %w", id, err)
|
|
188
|
+
}
|
|
189
|
+
return user, nil
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// 错误检查
|
|
193
|
+
func handleUser(id int) error {
|
|
194
|
+
user, err := getUser(id)
|
|
195
|
+
if err != nil {
|
|
196
|
+
if errors.Is(err, ErrNotFound) {
|
|
197
|
+
return nil // 忽略未找到
|
|
198
|
+
}
|
|
199
|
+
return err
|
|
200
|
+
}
|
|
201
|
+
// 处理 user
|
|
202
|
+
return nil
|
|
203
|
+
}
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
## 测试
|
|
207
|
+
|
|
208
|
+
```go
|
|
209
|
+
package main
|
|
210
|
+
|
|
211
|
+
import (
|
|
212
|
+
"testing"
|
|
213
|
+
"github.com/stretchr/testify/assert"
|
|
214
|
+
)
|
|
215
|
+
|
|
216
|
+
func TestAdd(t *testing.T) {
|
|
217
|
+
result := Add(1, 2)
|
|
218
|
+
assert.Equal(t, 3, result)
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
// 表驱动测试
|
|
222
|
+
func TestAddTable(t *testing.T) {
|
|
223
|
+
tests := []struct {
|
|
224
|
+
name string
|
|
225
|
+
a, b int
|
|
226
|
+
expected int
|
|
227
|
+
}{
|
|
228
|
+
{"positive", 1, 2, 3},
|
|
229
|
+
{"zero", 0, 0, 0},
|
|
230
|
+
{"negative", -1, 1, 0},
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
for _, tt := range tests {
|
|
234
|
+
t.Run(tt.name, func(t *testing.T) {
|
|
235
|
+
assert.Equal(t, tt.expected, Add(tt.a, tt.b))
|
|
236
|
+
})
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Benchmark
|
|
241
|
+
func BenchmarkAdd(b *testing.B) {
|
|
242
|
+
for i := 0; i < b.N; i++ {
|
|
243
|
+
Add(1, 2)
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
```bash
|
|
249
|
+
go test ./...
|
|
250
|
+
go test -v
|
|
251
|
+
go test -cover
|
|
252
|
+
go test -bench=.
|
|
253
|
+
go test -race # 竞态检测
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## CLI 工具
|
|
257
|
+
|
|
258
|
+
### Cobra
|
|
259
|
+
```go
|
|
260
|
+
package main
|
|
261
|
+
|
|
262
|
+
import (
|
|
263
|
+
"fmt"
|
|
264
|
+
"github.com/spf13/cobra"
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
var rootCmd = &cobra.Command{
|
|
268
|
+
Use: "myapp",
|
|
269
|
+
Short: "My CLI application",
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
var serveCmd = &cobra.Command{
|
|
273
|
+
Use: "serve",
|
|
274
|
+
Short: "Start the server",
|
|
275
|
+
Run: func(cmd *cobra.Command, args []string) {
|
|
276
|
+
port, _ := cmd.Flags().GetInt("port")
|
|
277
|
+
fmt.Printf("Starting server on port %d\n", port)
|
|
278
|
+
},
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
func init() {
|
|
282
|
+
serveCmd.Flags().IntP("port", "p", 8080, "Port to listen on")
|
|
283
|
+
rootCmd.AddCommand(serveCmd)
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
func main() {
|
|
287
|
+
rootCmd.Execute()
|
|
288
|
+
}
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## 项目结构
|
|
292
|
+
|
|
293
|
+
```
|
|
294
|
+
myproject/
|
|
295
|
+
├── go.mod
|
|
296
|
+
├── go.sum
|
|
297
|
+
├── main.go
|
|
298
|
+
├── cmd/
|
|
299
|
+
│ └── myapp/
|
|
300
|
+
│ └── main.go
|
|
301
|
+
├── internal/
|
|
302
|
+
│ ├── handler/
|
|
303
|
+
│ ├── service/
|
|
304
|
+
│ └── repository/
|
|
305
|
+
├── pkg/
|
|
306
|
+
│ └── utils/
|
|
307
|
+
└── tests/
|
|
308
|
+
```
|
|
309
|
+
|
|
310
|
+
## 常用库
|
|
311
|
+
|
|
312
|
+
| 库 | 用途 |
|
|
313
|
+
|---|------|
|
|
314
|
+
| gin/echo | Web 框架 |
|
|
315
|
+
| gorm | ORM |
|
|
316
|
+
| cobra | CLI |
|
|
317
|
+
| viper | 配置 |
|
|
318
|
+
| zap/zerolog | 日志 |
|
|
319
|
+
| testify | 测试 |
|
|
320
|
+
| wire | 依赖注入 |
|
|
321
|
+
|
|
322
|
+
---
|
|
323
|
+
|