ccg-ros2-workflow 2.2.1 → 3.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/README.md +211 -96
- package/README.zh-CN.md +256 -0
- package/dist/cli.mjs +15 -15
- package/dist/index.d.mts +61 -34
- package/dist/index.d.ts +61 -34
- package/dist/index.mjs +4 -4
- package/dist/shared/ccg-ros2-workflow.Bhm8c7P1.mjs +5154 -0
- package/package.json +31 -12
- package/templates/codex/AGENTS.md +348 -0
- package/templates/codex/agents/ccg-implement.toml +73 -0
- package/templates/codex/agents/ccg-research.toml +73 -0
- package/templates/codex/agents/ccg-review.toml +82 -0
- package/templates/codex/config.toml +21 -0
- package/templates/codex/hooks/ccg-workflow.py +253 -0
- package/templates/codex/hooks.json +15 -0
- package/templates/commands/agents/planner.md +97 -122
- package/templates/commands/agents/system-integrator.md +2 -2
- 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/commands/commit.md +30 -1
- package/templates/commands/context.md +332 -0
- package/templates/commands/go.md +206 -0
- package/templates/commands/init.md +1 -1
- package/templates/commands/spec-impl.md +41 -21
- package/templates/commands/spec-init.md +21 -27
- package/templates/commands/spec-plan.md +54 -21
- package/templates/commands/spec-research.md +78 -26
- package/templates/commands/spec-review.md +20 -16
- package/templates/{commands → commands-legacy}/analyze.md +1 -1
- package/templates/commands-legacy/backend.md +224 -0
- package/templates/commands-legacy/codex-exec.md +411 -0
- package/templates/{commands → commands-legacy}/debug.md +1 -1
- package/templates/commands-legacy/enhance.md +55 -0
- package/templates/{commands → commands-legacy}/feat.md +2 -2
- package/templates/commands-legacy/frontend.md +213 -0
- package/templates/{commands → commands-legacy}/optimize.md +1 -1
- package/templates/{commands → commands-legacy}/plan.md +1 -15
- package/templates/{commands → commands-legacy}/team-plan.md +1 -1
- package/templates/commands-legacy/team.md +475 -0
- package/templates/{commands → commands-legacy}/test.md +1 -1
- package/templates/commands-legacy/workflow.md +283 -0
- package/templates/engine/model-router.md +123 -0
- package/templates/engine/phase-guide.md +207 -0
- package/templates/engine/strategies/debug-investigate.md +169 -0
- package/templates/engine/strategies/deep-research.md +141 -0
- package/templates/engine/strategies/direct-fix.md +108 -0
- package/templates/engine/strategies/full-collaborate.md +389 -0
- package/templates/engine/strategies/git-action.md +43 -0
- package/templates/engine/strategies/guided-develop.md +282 -0
- package/templates/engine/strategies/optimize-measure.md +103 -0
- package/templates/engine/strategies/quick-implement.md +96 -0
- package/templates/engine/strategies/refactor-safely.md +180 -0
- package/templates/engine/strategies/review-audit.md +123 -0
- package/templates/hooks/session-start.js +100 -0
- package/templates/hooks/skill-router.js +144 -0
- package/templates/hooks/subagent-context.js +161 -0
- package/templates/hooks/task-utils.js +190 -0
- package/templates/hooks/workflow-state.js +55 -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/output-styles/engineer-professional.md +20 -3
- package/templates/output-styles/laowang-engineer.md +2 -2
- package/templates/prompts/antigravity/analyzer.md +59 -0
- package/templates/prompts/antigravity/architect.md +55 -0
- package/templates/prompts/antigravity/builder.md +52 -0
- package/templates/prompts/antigravity/debugger.md +48 -0
- package/templates/prompts/antigravity/frontend.md +50 -0
- package/templates/prompts/antigravity/optimizer.md +40 -0
- package/templates/prompts/antigravity/reviewer.md +67 -0
- package/templates/prompts/antigravity/tester.md +39 -0
- package/templates/prompts/claude/debugger.md +1 -1
- package/templates/prompts/claude/reviewer.md +1 -1
- package/templates/prompts/codex/analyzer.md +8 -0
- package/templates/prompts/codex/architect.md +9 -1
- package/templates/prompts/codex/builder.md +61 -0
- package/templates/prompts/codex/debugger.md +9 -1
- package/templates/prompts/codex/optimizer.md +7 -0
- package/templates/prompts/codex/reviewer.md +7 -0
- package/templates/prompts/codex/tester.md +8 -1
- package/templates/prompts/gemini/analyzer.md +11 -3
- package/templates/prompts/gemini/architect.md +10 -2
- package/templates/prompts/gemini/debugger.md +8 -0
- package/templates/prompts/gemini/frontend.md +10 -2
- package/templates/prompts/gemini/optimizer.md +9 -2
- package/templates/prompts/gemini/reviewer.md +7 -0
- package/templates/prompts/gemini/tester.md +8 -1
- package/templates/rules/ccg-skill-routing.md +91 -0
- package/templates/rules/ccg-skills.md +65 -0
- package/templates/skills/SKILL.md +92 -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 +369 -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 +487 -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/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/ros2-control/SKILL.md +206 -0
- package/templates/skills/domains/ros2-hardware/SKILL.md +277 -0
- package/templates/skills/domains/ros2-manipulation/SKILL.md +237 -0
- package/templates/skills/domains/ros2-navigation/SKILL.md +196 -0
- package/templates/skills/domains/ros2-perception/SKILL.md +166 -0
- package/templates/skills/domains/ros2-upper-app/SKILL.md +50 -0
- package/templates/skills/domains/ros2-upper-app/launch-files.md +224 -0
- package/templates/skills/domains/ros2-upper-app/parameters.md +192 -0
- package/templates/skills/domains/ros2-upper-app/python-nodes.md +249 -0
- package/templates/skills/domains/ros2-upper-app/rviz-config.md +158 -0
- package/templates/skills/domains/ros2-upper-app/simulation.md +225 -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/orchestration/multi-agent/SKILL.md +533 -0
- package/templates/skills/run_skill.js +129 -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/gen-docs/SKILL.md +116 -0
- package/templates/skills/tools/gen-docs/scripts/doc_generator.js +435 -0
- package/templates/skills/tools/lib/shared.js +98 -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
- package/templates/skills/tools/verify-change/SKILL.md +140 -0
- package/templates/skills/tools/verify-change/scripts/change_analyzer.js +289 -0
- package/templates/skills/tools/verify-module/SKILL.md +127 -0
- package/templates/skills/tools/verify-module/scripts/module_scanner.js +171 -0
- package/templates/skills/tools/verify-quality/SKILL.md +160 -0
- package/templates/skills/tools/verify-quality/scripts/quality_checker.js +337 -0
- package/templates/skills/tools/verify-security/SKILL.md +143 -0
- package/templates/skills/tools/verify-security/scripts/security_scanner.js +283 -0
- package/templates/spec/guides/index.md +30 -0
- package/templates/spec/low-control/index.md +31 -0
- package/templates/spec/upper-app/index.md +31 -0
- package/bin/codeagent-wrapper-darwin-amd64 +0 -0
- package/bin/codeagent-wrapper-darwin-arm64 +0 -0
- package/bin/codeagent-wrapper-linux-amd64 +0 -0
- package/bin/codeagent-wrapper-linux-arm64 +0 -0
- package/bin/codeagent-wrapper-windows-amd64.exe +0 -0
- package/bin/codeagent-wrapper-windows-arm64.exe +0 -0
- package/dist/shared/ccg-ros2-workflow.DRytDWqb.mjs +0 -2274
- package/templates/commands/backend.md +0 -162
- package/templates/commands/enhance.md +0 -36
- package/templates/commands/frontend.md +0 -162
- package/templates/commands/workflow.md +0 -202
- /package/templates/{commands → commands-legacy}/execute.md +0 -0
- /package/templates/{commands → commands-legacy}/review.md +0 -0
- /package/templates/{commands → commands-legacy}/team-exec.md +0 -0
- /package/templates/{commands → commands-legacy}/team-research.md +0 -0
- /package/templates/{commands → commands-legacy}/team-review.md +0 -0
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cpp
|
|
3
|
+
description: C/C++ 开发(含 ROS2 C++ 节点)。系统编程、性能优化、内存管理、ROS2 节点开发。当用户提到 C、C++、CMake、内存、指针、ROS2、rclcpp、生命周期节点时使用。
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# 📜 符箓秘典 · C/C++(ROS2 增强版)
|
|
7
|
+
|
|
8
|
+
## ROS2 C++ 开发上下文(底层控制核心)
|
|
9
|
+
|
|
10
|
+
ROS2 项目中,C++ 节点承担**底层控制**职责:硬件驱动、实时控制算法、关键性能路径。
|
|
11
|
+
|
|
12
|
+
### rclcpp 核心模式
|
|
13
|
+
|
|
14
|
+
```cpp
|
|
15
|
+
#include <rclcpp/rclcpp.hpp>
|
|
16
|
+
#include <sensor_msgs/msg/laser_scan.hpp>
|
|
17
|
+
#include <geometry_msgs/msg/twist.hpp>
|
|
18
|
+
|
|
19
|
+
class MotorDriverNode : public rclcpp::Node {
|
|
20
|
+
public:
|
|
21
|
+
MotorDriverNode() : Node("motor_driver") {
|
|
22
|
+
// QoS 策略:控制指令需要 Reliable
|
|
23
|
+
auto qos = rclcpp::QoS(10).reliable();
|
|
24
|
+
|
|
25
|
+
cmd_sub_ = this->create_subscription<geometry_msgs::msg::Twist>(
|
|
26
|
+
"cmd_vel", qos,
|
|
27
|
+
[this](const geometry_msgs::msg::Twist::SharedPtr msg) {
|
|
28
|
+
this->cmd_callback(msg);
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
odom_pub_ = this->create_publisher<nav_msgs::msg::Odometry>("odom", qos);
|
|
32
|
+
|
|
33
|
+
// 高频控制循环 (100Hz)
|
|
34
|
+
timer_ = this->create_wall_timer(
|
|
35
|
+
std::chrono::milliseconds(10),
|
|
36
|
+
std::bind(&MotorDriverNode::control_loop, this));
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
private:
|
|
40
|
+
rclcpp::Subscription<geometry_msgs::msg::Twist>::SharedPtr cmd_sub_;
|
|
41
|
+
rclcpp::Publisher<nav_msgs::msg::Odometry>::SharedPtr odom_pub_;
|
|
42
|
+
rclcpp::TimerBase::SharedPtr timer_;
|
|
43
|
+
};
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### 生命周期节点 (Lifecycle Node)
|
|
47
|
+
|
|
48
|
+
适用场景:硬件驱动、需要状态管理的关键节点。
|
|
49
|
+
|
|
50
|
+
```cpp
|
|
51
|
+
#include <rclcpp_lifecycle/lifecycle_node.hpp>
|
|
52
|
+
|
|
53
|
+
class LidarDriver : public rclcpp_lifecycle::LifecycleNode {
|
|
54
|
+
public:
|
|
55
|
+
CallbackReturn on_configure(const rclcpp_lifecycle::State&) {
|
|
56
|
+
// 初始化硬件连接
|
|
57
|
+
return CallbackReturn::SUCCESS;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
CallbackReturn on_activate(const rclcpp_lifecycle::State&) {
|
|
61
|
+
// 启动数据采集
|
|
62
|
+
return CallbackReturn::SUCCESS;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
CallbackReturn on_deactivate(const rclcpp_lifecycle::State&) {
|
|
66
|
+
// 停止数据采集,保留连接
|
|
67
|
+
return CallbackReturn::SUCCESS;
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
### CMakeLists.txt 标准模板
|
|
73
|
+
|
|
74
|
+
```cmake
|
|
75
|
+
cmake_minimum_required(VERSION 3.8)
|
|
76
|
+
project(my_robot_driver)
|
|
77
|
+
|
|
78
|
+
if(CMAKE_COMPILER_IS_GNUCXX OR CMAKE_CXX_COMPILER_ID MATCHES "Clang")
|
|
79
|
+
add_compile_options(-Wall -Wextra -Wpedantic -O2)
|
|
80
|
+
endif()
|
|
81
|
+
|
|
82
|
+
find_package(ament_cmake REQUIRED)
|
|
83
|
+
find_package(rclcpp REQUIRED)
|
|
84
|
+
find_package(sensor_msgs REQUIRED)
|
|
85
|
+
find_package(geometry_msgs REQUIRED)
|
|
86
|
+
|
|
87
|
+
add_executable(motor_driver src/motor_driver.cpp)
|
|
88
|
+
ament_target_dependencies(motor_driver
|
|
89
|
+
rclcpp sensor_msgs geometry_msgs)
|
|
90
|
+
|
|
91
|
+
install(TARGETS motor_driver DESTINATION lib/${PROJECT_NAME})
|
|
92
|
+
|
|
93
|
+
ament_package()
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### ROS2 实时性约束
|
|
97
|
+
|
|
98
|
+
| 场景 | 推荐策略 |
|
|
99
|
+
|------|----------|
|
|
100
|
+
| 控制循环 (>= 100Hz) | wall_timer + 独立 callback group + Reentrant |
|
|
101
|
+
| 传感器数据 | Best Effort QoS,丢包优于阻塞 |
|
|
102
|
+
| 关键控制指令 | Reliable QoS,深度 10 |
|
|
103
|
+
| 配置参数 | Transient Local,新订阅者获取最新 |
|
|
104
|
+
|
|
105
|
+
### 线程安全(多回调场景)
|
|
106
|
+
|
|
107
|
+
```cpp
|
|
108
|
+
// 使用 mutex 保护共享状态
|
|
109
|
+
std::mutex state_mutex_;
|
|
110
|
+
geometry_msgs::msg::Twist current_cmd_;
|
|
111
|
+
|
|
112
|
+
void cmd_callback(const geometry_msgs::msg::Twist::SharedPtr msg) {
|
|
113
|
+
std::lock_guard<std::mutex> lock(state_mutex_);
|
|
114
|
+
current_cmd_ = *msg;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
void control_loop() {
|
|
118
|
+
geometry_msgs::msg::Twist cmd;
|
|
119
|
+
{
|
|
120
|
+
std::lock_guard<std::mutex> lock(state_mutex_);
|
|
121
|
+
cmd = current_cmd_;
|
|
122
|
+
}
|
|
123
|
+
// 使用 cmd 计算控制量
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
---
|
|
128
|
+
|
|
129
|
+
## 通用 C++ 知识(以下保持原样)
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
## 现代 C++ (C++17/20)
|
|
133
|
+
|
|
134
|
+
### 智能指针
|
|
135
|
+
```cpp
|
|
136
|
+
#include <memory>
|
|
137
|
+
|
|
138
|
+
// unique_ptr - 独占所有权
|
|
139
|
+
auto ptr = std::make_unique<MyClass>(args);
|
|
140
|
+
ptr->method();
|
|
141
|
+
|
|
142
|
+
// shared_ptr - 共享所有权
|
|
143
|
+
auto shared = std::make_shared<MyClass>(args);
|
|
144
|
+
auto copy = shared; // 引用计数 +1
|
|
145
|
+
|
|
146
|
+
// weak_ptr - 弱引用,不增加引用计数
|
|
147
|
+
std::weak_ptr<MyClass> weak = shared;
|
|
148
|
+
if (auto locked = weak.lock()) {
|
|
149
|
+
locked->method();
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
### 容器与算法
|
|
154
|
+
```cpp
|
|
155
|
+
#include <vector>
|
|
156
|
+
#include <algorithm>
|
|
157
|
+
#include <ranges>
|
|
158
|
+
|
|
159
|
+
std::vector<int> nums = {1, 2, 3, 4, 5};
|
|
160
|
+
|
|
161
|
+
// 范围 for
|
|
162
|
+
for (const auto& n : nums) {
|
|
163
|
+
std::cout << n << std::endl;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// 算法
|
|
167
|
+
auto it = std::find(nums.begin(), nums.end(), 3);
|
|
168
|
+
std::sort(nums.begin(), nums.end());
|
|
169
|
+
|
|
170
|
+
// C++20 Ranges
|
|
171
|
+
auto even = nums | std::views::filter([](int n) { return n % 2 == 0; });
|
|
172
|
+
auto squared = nums | std::views::transform([](int n) { return n * n; });
|
|
173
|
+
```
|
|
174
|
+
|
|
175
|
+
### Lambda 表达式
|
|
176
|
+
```cpp
|
|
177
|
+
// 基础 lambda
|
|
178
|
+
auto add = [](int a, int b) { return a + b; };
|
|
179
|
+
|
|
180
|
+
// 捕获
|
|
181
|
+
int x = 10;
|
|
182
|
+
auto capture_val = [x]() { return x; }; // 值捕获
|
|
183
|
+
auto capture_ref = [&x]() { return x; }; // 引用捕获
|
|
184
|
+
auto capture_all = [=]() { return x; }; // 全部值捕获
|
|
185
|
+
auto capture_all_ref = [&]() { return x; }; // 全部引用捕获
|
|
186
|
+
|
|
187
|
+
// 泛型 lambda (C++14)
|
|
188
|
+
auto generic = [](auto a, auto b) { return a + b; };
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
### 并发编程
|
|
192
|
+
```cpp
|
|
193
|
+
#include <thread>
|
|
194
|
+
#include <mutex>
|
|
195
|
+
#include <future>
|
|
196
|
+
|
|
197
|
+
// 线程
|
|
198
|
+
std::thread t([]() {
|
|
199
|
+
std::cout << "Hello from thread" << std::endl;
|
|
200
|
+
});
|
|
201
|
+
t.join();
|
|
202
|
+
|
|
203
|
+
// 互斥锁
|
|
204
|
+
std::mutex mtx;
|
|
205
|
+
{
|
|
206
|
+
std::lock_guard<std::mutex> lock(mtx);
|
|
207
|
+
// 临界区
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// async/future
|
|
211
|
+
auto future = std::async(std::launch::async, []() {
|
|
212
|
+
return compute_result();
|
|
213
|
+
});
|
|
214
|
+
auto result = future.get();
|
|
215
|
+
|
|
216
|
+
// 条件变量
|
|
217
|
+
std::condition_variable cv;
|
|
218
|
+
std::unique_lock<std::mutex> lock(mtx);
|
|
219
|
+
cv.wait(lock, []() { return ready; });
|
|
220
|
+
```
|
|
221
|
+
|
|
222
|
+
## 内存管理
|
|
223
|
+
|
|
224
|
+
### RAII 模式
|
|
225
|
+
```cpp
|
|
226
|
+
class FileHandle {
|
|
227
|
+
public:
|
|
228
|
+
FileHandle(const char* path) : file(fopen(path, "r")) {
|
|
229
|
+
if (!file) throw std::runtime_error("Failed to open file");
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
~FileHandle() {
|
|
233
|
+
if (file) fclose(file);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// 禁止拷贝
|
|
237
|
+
FileHandle(const FileHandle&) = delete;
|
|
238
|
+
FileHandle& operator=(const FileHandle&) = delete;
|
|
239
|
+
|
|
240
|
+
// 允许移动
|
|
241
|
+
FileHandle(FileHandle&& other) noexcept : file(other.file) {
|
|
242
|
+
other.file = nullptr;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
private:
|
|
246
|
+
FILE* file;
|
|
247
|
+
};
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### 内存安全检查
|
|
251
|
+
```bash
|
|
252
|
+
# AddressSanitizer
|
|
253
|
+
g++ -fsanitize=address -g main.cpp -o main
|
|
254
|
+
./main
|
|
255
|
+
|
|
256
|
+
# Valgrind
|
|
257
|
+
valgrind --leak-check=full ./main
|
|
258
|
+
|
|
259
|
+
# 静态分析
|
|
260
|
+
clang-tidy main.cpp
|
|
261
|
+
cppcheck main.cpp
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
## CMake
|
|
265
|
+
|
|
266
|
+
### CMakeLists.txt
|
|
267
|
+
```cmake
|
|
268
|
+
cmake_minimum_required(VERSION 3.16)
|
|
269
|
+
project(MyProject VERSION 1.0.0 LANGUAGES CXX)
|
|
270
|
+
|
|
271
|
+
set(CMAKE_CXX_STANDARD 17)
|
|
272
|
+
set(CMAKE_CXX_STANDARD_REQUIRED ON)
|
|
273
|
+
|
|
274
|
+
# 添加可执行文件
|
|
275
|
+
add_executable(myapp
|
|
276
|
+
src/main.cpp
|
|
277
|
+
src/utils.cpp
|
|
278
|
+
)
|
|
279
|
+
|
|
280
|
+
# 添加库
|
|
281
|
+
add_library(mylib STATIC
|
|
282
|
+
src/lib.cpp
|
|
283
|
+
)
|
|
284
|
+
|
|
285
|
+
# 链接库
|
|
286
|
+
target_link_libraries(myapp PRIVATE mylib)
|
|
287
|
+
|
|
288
|
+
# 包含目录
|
|
289
|
+
target_include_directories(myapp PRIVATE ${CMAKE_SOURCE_DIR}/include)
|
|
290
|
+
|
|
291
|
+
# 查找外部库
|
|
292
|
+
find_package(Threads REQUIRED)
|
|
293
|
+
target_link_libraries(myapp PRIVATE Threads::Threads)
|
|
294
|
+
|
|
295
|
+
# 测试
|
|
296
|
+
enable_testing()
|
|
297
|
+
add_executable(tests tests/test_main.cpp)
|
|
298
|
+
add_test(NAME MyTests COMMAND tests)
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### 构建
|
|
302
|
+
```bash
|
|
303
|
+
mkdir build && cd build
|
|
304
|
+
cmake ..
|
|
305
|
+
cmake --build .
|
|
306
|
+
ctest # 运行测试
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## 测试
|
|
310
|
+
|
|
311
|
+
### Google Test
|
|
312
|
+
```cpp
|
|
313
|
+
#include <gtest/gtest.h>
|
|
314
|
+
|
|
315
|
+
TEST(MathTest, Add) {
|
|
316
|
+
EXPECT_EQ(add(1, 2), 3);
|
|
317
|
+
EXPECT_EQ(add(-1, 1), 0);
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
TEST(MathTest, Divide) {
|
|
321
|
+
EXPECT_DOUBLE_EQ(divide(10, 2), 5.0);
|
|
322
|
+
EXPECT_THROW(divide(1, 0), std::invalid_argument);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
// Fixture
|
|
326
|
+
class UserTest : public ::testing::Test {
|
|
327
|
+
protected:
|
|
328
|
+
void SetUp() override {
|
|
329
|
+
user = std::make_unique<User>("Alice");
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
std::unique_ptr<User> user;
|
|
333
|
+
};
|
|
334
|
+
|
|
335
|
+
TEST_F(UserTest, GetName) {
|
|
336
|
+
EXPECT_EQ(user->getName(), "Alice");
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
## 项目结构
|
|
341
|
+
|
|
342
|
+
```
|
|
343
|
+
myproject/
|
|
344
|
+
├── CMakeLists.txt
|
|
345
|
+
├── include/
|
|
346
|
+
│ └── myproject/
|
|
347
|
+
│ ├── utils.h
|
|
348
|
+
│ └── types.h
|
|
349
|
+
├── src/
|
|
350
|
+
│ ├── main.cpp
|
|
351
|
+
│ └── utils.cpp
|
|
352
|
+
├── tests/
|
|
353
|
+
│ └── test_main.cpp
|
|
354
|
+
└── build/
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## 常用库
|
|
358
|
+
|
|
359
|
+
| 库 | 用途 |
|
|
360
|
+
|---|------|
|
|
361
|
+
| Boost | 通用库集合 |
|
|
362
|
+
| fmt | 格式化输出 |
|
|
363
|
+
| spdlog | 日志 |
|
|
364
|
+
| nlohmann/json | JSON |
|
|
365
|
+
| Catch2/GTest | 测试 |
|
|
366
|
+
| OpenSSL | 加密 |
|
|
367
|
+
|
|
368
|
+
---
|
|
369
|
+
|
|
@@ -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
|
+
|