# Common Bugs Checklist Language-specific bugs and issues to watch for during code review. ## Universal Issues ### Logic Errors - [ ] Off-by-one errors in loops and array access - [ ] Incorrect boolean logic (De Morgan's law violations) - [ ] Missing null/undefined checks - [ ] Race conditions in concurrent code - [ ] Incorrect comparison operators (== vs ===, = vs ==) - [ ] Integer overflow/underflow - [ ] Floating point comparison issues ### Resource Management - [ ] Memory leaks (unclosed connections, listeners) - [ ] File handles not closed - [ ] Database connections not released - [ ] Event listeners not removed - [ ] Timers/intervals not cleared ### Error Handling - [ ] Swallowed exceptions (empty catch blocks) - [ ] Generic exception handling hiding specific errors - [ ] Missing error propagation - [ ] Incorrect error types thrown - [ ] Missing finally/cleanup blocks ## TypeScript/JavaScript ### Type Issues ```typescript // ❌ Using any defeats type safety function process(data: any) { return data.value; } // ✅ Use proper types interface Data { value: string; } function process(data: Data) { return data.value; } ``` ### Async/Await Pitfalls ```typescript // ❌ Missing await async function fetch() { const data = fetchData(); // Missing await! return data.json(); } // ❌ Unhandled promise rejection async function risky() { const result = await fetchData(); // No try-catch return result; } // ✅ Proper error handling async function safe() { try { const result = await fetchData(); return result; } catch (error) { console.error('Fetch failed:', error); throw error; } } ``` ### React Specific #### Hooks 规则违反 ```tsx // ❌ 条件调用 Hooks — 违反 Hooks 规则 function BadComponent({ show }) { if (show) { const [value, setValue] = useState(0); // Error! } return
...
; } // ✅ Hooks 必须在顶层无条件调用 function GoodComponent({ show }) { const [value, setValue] = useState(0); if (!show) return null; return
{value}
; } // ❌ 循环中调用 Hooks function BadLoop({ items }) { items.forEach(item => { const [selected, setSelected] = useState(false); // Error! }); } // ✅ 将状态提升或使用不同的数据结构 function GoodLoop({ items }) { const [selectedIds, setSelectedIds] = useState>(new Set()); return items.map(item => ( )); } ``` #### useEffect 常见错误 ```tsx // ❌ 依赖数组不完整 — stale closure function StaleClosureExample({ userId, onSuccess }) { const [data, setData] = useState(null); useEffect(() => { fetchData(userId).then(result => { setData(result); onSuccess(result); // onSuccess 可能是 stale 的! }); }, [userId]); // 缺少 onSuccess 依赖 } // ✅ 完整的依赖数组 useEffect(() => { fetchData(userId).then(result => { setData(result); onSuccess(result); }); }, [userId, onSuccess]); // ❌ 无限循环 — 在 effect 中更新依赖 function InfiniteLoop() { const [count, setCount] = useState(0); useEffect(() => { setCount(count + 1); // 触发重渲染,又触发 effect }, [count]); // 无限循环! } // ❌ 缺少清理函数 — 内存泄漏 function MemoryLeak({ userId }) { const [user, setUser] = useState(null); useEffect(() => { fetchUser(userId).then(setUser); // 组件卸载后仍然调用 setUser }, [userId]); } // ✅ 正确的清理 function NoLeak({ userId }) { const [user, setUser] = useState(null); useEffect(() => { let cancelled = false; fetchUser(userId).then(data => { if (!cancelled) setUser(data); }); return () => { cancelled = true; }; }, [userId]); } // ❌ useEffect 用于派生状态(反模式) function BadDerived({ items }) { const [total, setTotal] = useState(0); useEffect(() => { setTotal(items.reduce((a, b) => a + b.price, 0)); }, [items]); // 不必要的 effect + 额外渲染 } // ✅ 直接计算或用 useMemo function GoodDerived({ items }) { const total = useMemo( () => items.reduce((a, b) => a + b.price, 0), [items] ); } // ❌ useEffect 用于事件响应 function BadEvent() { const [query, setQuery] = useState(''); useEffect(() => { if (query) logSearch(query); // 应该在事件处理器中 }, [query]); } // ✅ 副作用在事件处理器中 function GoodEvent() { const handleSearch = (q: string) => { setQuery(q); logSearch(q); }; } ``` #### useMemo / useCallback 误用 ```tsx // ❌ 过度优化 — 常量不需要 memo function OverOptimized() { const config = useMemo(() => ({ api: '/v1' }), []); // 无意义 const noop = useCallback(() => {}, []); // 无意义 } // ❌ 空依赖的 useMemo(可能隐藏 bug) function EmptyDeps({ user }) { const greeting = useMemo(() => `Hello ${user.name}`, []); // user 变化时 greeting 不更新! } // ❌ useCallback 依赖总是变化 function UselessCallback({ data }) { const process = useCallback(() => { return data.map(transform); }, [data]); // 如果 data 每次都是新引用,完全无效 } // ❌ useMemo/useCallback 没有配合 React.memo function Parent() { const data = useMemo(() => compute(), []); const handler = useCallback(() => {}, []); return ; // Child 没有用 React.memo,这些优化毫无意义 } // ✅ 正确的优化组合 const MemoChild = React.memo(function Child({ data, onClick }) { return ; }); function Parent() { const data = useMemo(() => expensiveCompute(), [dep]); const handler = useCallback(() => {}, []); return ; } ``` #### 组件设计问题 ```tsx // ❌ 在组件内定义组件 function Parent() { // 每次渲染都创建新的 Child 函数,导致完全重新挂载 const Child = () =>
child
; return ; } // ✅ 组件定义在外部 const Child = () =>
child
; function Parent() { return ; } // ❌ Props 总是新引用 — 破坏 memo function BadProps() { return ( handle()} // 每次渲染新函数 items={data.filter(x => x)} // 每次渲染新数组 /> ); } // ❌ 直接修改 props function MutateProps({ user }) { user.name = 'Changed'; // 永远不要这样做! return
{user.name}
; } ``` #### Server Components 错误 (React 19+) ```tsx // ❌ 在 Server Component 中使用客户端 API // app/page.tsx (默认是 Server Component) export default function Page() { const [count, setCount] = useState(0); // Error! useEffect(() => {}, []); // Error! return ; // Error! } // ✅ 交互逻辑移到 Client Component // app/counter.tsx 'use client'; export function Counter() { const [count, setCount] = useState(0); return ; } // app/page.tsx import { Counter } from './counter'; export default async function Page() { const data = await fetchData(); // Server Component 可以直接 await return ; } // ❌ 在父组件标记 'use client',整个子树变成客户端 // layout.tsx 'use client'; // 坏主意!所有子组件都变成客户端组件 export default function Layout({ children }) { ... } ``` #### 测试常见错误 ```tsx // ❌ 使用 container 查询 const { container } = render(); const button = container.querySelector('button'); // 不推荐 // ✅ 使用 screen 和语义查询 render(); const button = screen.getByRole('button', { name: /submit/i }); // ❌ 使用 fireEvent fireEvent.click(button); // ✅ 使用 userEvent await userEvent.click(button); // ❌ 测试实现细节 expect(component.state.isOpen).toBe(true); // ✅ 测试行为 expect(screen.getByRole('dialog')).toBeVisible(); // ❌ 等待同步查询 await screen.getByText('Hello'); // getBy 是同步的 // ✅ 异步用 findBy await screen.findByText('Hello'); // findBy 会等待 ``` ### React Common Mistakes Checklist - [ ] Hooks 不在顶层调用(条件/循环中) - [ ] useEffect 依赖数组不完整 - [ ] useEffect 缺少清理函数 - [ ] useEffect 用于派生状态计算 - [ ] useMemo/useCallback 过度使用 - [ ] useMemo/useCallback 没配合 React.memo - [ ] 在组件内定义子组件 - [ ] Props 是新对象/函数引用(传给 memo 组件时) - [ ] 直接修改 props - [ ] 列表缺少 key 或用 index 作为 key - [ ] Server Component 使用客户端 API - [ ] 'use client' 放在父组件导致整个树客户端化 - [ ] 测试使用 container 查询而非 screen - [ ] 测试实现细节而非行为 ### React 19 Actions & Forms 错误 ```tsx // === useActionState 错误 === // ❌ 在 Action 中直接 setState 而不是返回状态 const [state, action] = useActionState(async (prev, formData) => { setSomeState(newValue); // 错误!应该返回新状态 }, initialState); // ✅ 返回新状态 const [state, action] = useActionState(async (prev, formData) => { const result = await submitForm(formData); return { ...prev, data: result }; // 返回新状态 }, initialState); // ❌ 忘记处理 isPending const [state, action] = useActionState(submitAction, null); return ; // 用户可以重复点击 // ✅ 使用 isPending 禁用按钮 const [state, action, isPending] = useActionState(submitAction, null); return ; // === useFormStatus 错误 === // ❌ 在 form 同级调用 useFormStatus function Form() { const { pending } = useFormStatus(); // 永远是 undefined! return
; } // ✅ 在子组件中调用 function SubmitButton() { const { pending } = useFormStatus(); return ; } function Form() { return
; } // === useOptimistic 错误 === // ❌ 用于关键业务操作 function PaymentButton() { const [optimisticPaid, setPaid] = useOptimistic(false); const handlePay = async () => { setPaid(true); // 危险:显示已支付但可能失败 await processPayment(); }; } // ❌ 没有处理回滚后的 UI 状态 const [optimisticLikes, addLike] = useOptimistic(likes); // 失败后 UI 回滚,但用户可能困惑为什么点赞消失了 // ✅ 提供失败反馈 const handleLike = async () => { addLike(1); try { await likePost(); } catch { toast.error('点赞失败,请重试'); // 通知用户 } }; ``` ### React 19 Forms Checklist - [ ] useActionState 返回新状态而不是 setState - [ ] useActionState 正确使用 isPending 禁用提交 - [ ] useFormStatus 在 form 子组件中调用 - [ ] useOptimistic 不用于关键业务(支付、删除等) - [ ] useOptimistic 失败时有用户反馈 - [ ] Server Action 正确标记 'use server' ### Suspense & Streaming 错误 ```tsx // === Suspense 边界错误 === // ❌ 整个页面一个 Suspense——慢内容阻塞快内容 function BadPage() { return ( }> {/* 快 */} {/* 慢——阻塞整个页面 */} {/* 快 */} ); } // ✅ 独立边界,互不阻塞 function GoodPage() { return ( <> }> ); } // ❌ 没有 Error Boundary function NoErrorHandling() { return ( }> {/* 抛错导致白屏 */} ); } // ✅ Error Boundary + Suspense function WithErrorHandling() { return ( }> }> ); } // === use() Hook 错误 === // ❌ 在组件外创建 Promise(每次渲染新 Promise) function BadUse() { const data = use(fetchData()); // 每次渲染都创建新 Promise! return
{data}
; } // ✅ 在父组件创建,通过 props 传递 function Parent() { const dataPromise = useMemo(() => fetchData(), []); return ; } function Child({ dataPromise }) { const data = use(dataPromise); return
{data}
; } // === Next.js Streaming 错误 === // ❌ 在 layout.tsx 中 await 慢数据——阻塞所有子页面 // app/layout.tsx export default async function Layout({ children }) { const config = await fetchSlowConfig(); // 阻塞整个应用! return {children}; } // ✅ 将慢数据放在页面级别或使用 Suspense // app/layout.tsx export default function Layout({ children }) { return ( }> {children} ); } ``` ### Suspense Checklist - [ ] 慢内容有独立的 Suspense 边界 - [ ] 每个 Suspense 有对应的 Error Boundary - [ ] fallback 是有意义的骨架屏(不是简单 spinner) - [ ] use() 的 Promise 不在渲染时创建 - [ ] 没有在 layout 中 await 慢数据 - [ ] 嵌套层级不超过 3 层 ### TanStack Query 错误 ```tsx // === 查询配置错误 === // ❌ queryKey 不包含查询参数 function BadQuery({ userId, filters }) { const { data } = useQuery({ queryKey: ['users'], // 缺少 userId 和 filters! queryFn: () => fetchUsers(userId, filters), }); // userId 或 filters 变化时数据不会更新 } // ✅ queryKey 包含所有影响数据的参数 function GoodQuery({ userId, filters }) { const { data } = useQuery({ queryKey: ['users', userId, filters], queryFn: () => fetchUsers(userId, filters), }); } // ❌ staleTime: 0 导致过度请求 const { data } = useQuery({ queryKey: ['data'], queryFn: fetchData, // 默认 staleTime: 0,每次组件挂载/窗口聚焦都会 refetch }); // ✅ 设置合理的 staleTime const { data } = useQuery({ queryKey: ['data'], queryFn: fetchData, staleTime: 5 * 60 * 1000, // 5 分钟内不会自动 refetch }); // === useSuspenseQuery 错误 === // ❌ useSuspenseQuery + enabled(不支持) const { data } = useSuspenseQuery({ queryKey: ['user', userId], queryFn: () => fetchUser(userId), enabled: !!userId, // 错误!useSuspenseQuery 不支持 enabled }); // ✅ 条件渲染实现 function UserQuery({ userId }) { const { data } = useSuspenseQuery({ queryKey: ['user', userId], queryFn: () => fetchUser(userId), }); return ; } function Parent({ userId }) { if (!userId) return ; return ( }> ); } // === Mutation 错误 === // ❌ Mutation 成功后不 invalidate 查询 const mutation = useMutation({ mutationFn: updateUser, // 忘记 invalidate,UI 显示旧数据 }); // ✅ 成功后 invalidate 相关查询 const mutation = useMutation({ mutationFn: updateUser, onSuccess: () => { queryClient.invalidateQueries({ queryKey: ['users'] }); }, }); // ❌ 乐观更新不处理回滚 const mutation = useMutation({ mutationFn: updateTodo, onMutate: async (newTodo) => { queryClient.setQueryData(['todos'], (old) => [...old, newTodo]); // 没有保存旧数据,失败后无法回滚! }, }); // ✅ 完整的乐观更新 const mutation = useMutation({ mutationFn: updateTodo, onMutate: async (newTodo) => { await queryClient.cancelQueries({ queryKey: ['todos'] }); const previous = queryClient.getQueryData(['todos']); queryClient.setQueryData(['todos'], (old) => [...old, newTodo]); return { previous }; }, onError: (err, newTodo, context) => { queryClient.setQueryData(['todos'], context.previous); }, onSettled: () => { queryClient.invalidateQueries({ queryKey: ['todos'] }); }, }); // === v5 迁移错误 === // ❌ 使用废弃的 API const { data, isLoading } = useQuery(['key'], fetchFn); // v4 语法 // ✅ v5 单一对象参数 const { data, isPending } = useQuery({ queryKey: ['key'], queryFn: fetchFn, }); // ❌ 混淆 isPending 和 isLoading if (isLoading) return ; // v5 中 isLoading = isPending && isFetching // ✅ 根据意图选择 if (isPending) return ; // 没有缓存数据 // 或 if (isFetching) return ; // 正在后台刷新 ``` ### TanStack Query Checklist - [ ] queryKey 包含所有影响数据的参数 - [ ] 设置了合理的 staleTime(不是默认 0) - [ ] useSuspenseQuery 不使用 enabled - [ ] Mutation 成功后 invalidate 相关查询 - [ ] 乐观更新有完整的回滚逻辑 - [ ] v5 使用单一对象参数语法 - [ ] 理解 isPending vs isLoading vs isFetching ### TypeScript/JavaScript Common Mistakes - [ ] `==` instead of `===` - [ ] Modifying array/object during iteration - [ ] `this` context lost in callbacks - [ ] Missing `key` prop in lists - [ ] Closure capturing loop variable - [ ] parseInt without radix parameter ## Vue 3 ### 响应性丢失 ```vue ``` ### Props 响应性传递 ```vue ``` ### Watch 清理 ```vue ``` ### Computed 副作用 ```vue ``` ### 模板常见错误 ```vue ``` ### Common Mistakes - [ ] 解构 reactive 对象丢失响应性 - [ ] props 传递给 composable 时未保持响应性 - [ ] watch 异步回调无清理函数 - [ ] computed 中产生副作用 - [ ] v-for 使用 index 作为 key(列表会重排时) - [ ] v-if 和 v-for 在同一元素上 - [ ] defineProps 未使用 TypeScript 类型声明 - [ ] withDefaults 对象默认值未使用工厂函数 - [ ] 直接修改 props(而不是 emit) - [ ] watchEffect 依赖不明确导致过度触发 ## Python ### Mutable Default Arguments ```python # ❌ Bug: List shared across all calls def add_item(item, items=[]): items.append(item) return items # ✅ Correct def add_item(item, items=None): if items is None: items = [] items.append(item) return items ``` ### Exception Handling ```python # ❌ Catching everything, including KeyboardInterrupt try: risky_operation() except: pass # ✅ Catch specific exceptions try: risky_operation() except ValueError as e: logger.error(f"Invalid value: {e}") raise ``` ### Class Attributes ```python # ❌ Shared mutable class attribute class User: permissions = [] # Shared across all instances! # ✅ Initialize in __init__ class User: def __init__(self): self.permissions = [] ``` ### Common Mistakes - [ ] Using `is` instead of `==` for value comparison - [ ] Forgetting `self` parameter in methods - [ ] Modifying list while iterating - [ ] String concatenation in loops (use join) - [ ] Not closing files (use `with` statement) ## Rust ### 所有权与借用 ```rust // ❌ Use after move let s = String::from("hello"); let s2 = s; println!("{}", s); // Error: s was moved // ✅ Clone if needed (but consider if clone is necessary) let s = String::from("hello"); let s2 = s.clone(); println!("{}", s); // OK // ❌ 用 clone() 绕过借用检查器(反模式) fn process(data: &Data) { let owned = data.clone(); // 不必要的 clone do_something(owned); } // ✅ 正确使用借用 fn process(data: &Data) { do_something(data); // 传递引用 } // ❌ 在结构体中存储借用(通常是坏主意) struct Parser<'a> { input: &'a str, // 生命周期复杂化 position: usize, } // ✅ 使用拥有的数据 struct Parser { input: String, // 拥有数据,简化生命周期 position: usize, } // ❌ 迭代时修改集合 let mut vec = vec![1, 2, 3]; for item in &vec { vec.push(*item); // Error: cannot borrow as mutable } // ✅ 收集到新集合 let vec = vec![1, 2, 3]; let new_vec: Vec<_> = vec.iter().map(|x| x * 2).collect(); ``` ### Unsafe 代码审查 ```rust // ❌ unsafe 没有安全注释 unsafe { ptr::write(dest, value); } // ✅ 必须有 SAFETY 注释说明不变量 // SAFETY: dest 指针由 Vec::as_mut_ptr() 获得,保证: // 1. 指针有效且已对齐 // 2. 目标内存未被其他引用借用 // 3. 写入不会超出分配的容量 unsafe { ptr::write(dest, value); } // ❌ unsafe fn 没有 # Safety 文档 pub unsafe fn from_raw_parts(ptr: *mut T, len: usize) -> Self { ... } // ✅ 必须文档化安全契约 /// Creates a new instance from raw parts. /// /// # Safety /// /// - `ptr` must have been allocated via `GlobalAlloc` /// - `len` must be less than or equal to the allocated capacity /// - The caller must ensure no other references to the memory exist pub unsafe fn from_raw_parts(ptr: *mut T, len: usize) -> Self { ... } // ❌ 跨模块 unsafe 不变量 mod a { pub fn set_flag() { FLAG = true; } // 安全代码影响 unsafe } mod b { pub unsafe fn do_thing() { if FLAG { /* assumes FLAG means something */ } } } // ✅ 将 unsafe 边界封装在单一模块 mod safe_wrapper { // 所有 unsafe 逻辑在一个模块内 // 对外提供 safe API } ``` ### 异步/并发 ```rust // ❌ 在异步上下文中阻塞 async fn bad_fetch(url: &str) -> Result { let resp = reqwest::blocking::get(url)?; // 阻塞整个运行时! Ok(resp.text()?) } // ✅ 使用异步版本 async fn good_fetch(url: &str) -> Result { let resp = reqwest::get(url).await?; Ok(resp.text().await?) } // ❌ 跨 .await 持有 Mutex async fn bad_lock(mutex: &Mutex) { let guard = mutex.lock().unwrap(); some_async_op().await; // 持锁跨越 await! drop(guard); } // ✅ 缩短锁持有时间 async fn good_lock(mutex: &Mutex) { let data = { let guard = mutex.lock().unwrap(); guard.clone() // 获取数据后立即释放锁 }; some_async_op().await; // 处理 data } // ❌ 在异步函数中使用 std::sync::Mutex async fn bad_async_mutex(mutex: &std::sync::Mutex) { let _guard = mutex.lock().unwrap(); // 可能死锁 tokio::time::sleep(Duration::from_secs(1)).await; } // ✅ 使用 tokio::sync::Mutex(如果必须跨 await) async fn good_async_mutex(mutex: &tokio::sync::Mutex) { let _guard = mutex.lock().await; tokio::time::sleep(Duration::from_secs(1)).await; } // ❌ 忘记 Future 是惰性的 fn bad_spawn() { let future = async_operation(); // 没有执行! // future 被丢弃,什么都没发生 } // ✅ 必须 await 或 spawn async fn good_spawn() { async_operation().await; // 执行 // 或 tokio::spawn(async_operation()); // 后台执行 } // ❌ spawn 任务缺少 'static async fn bad_spawn_lifetime(data: &str) { tokio::spawn(async { println!("{}", data); // Error: data 不是 'static }); } // ✅ 使用 move 或 Arc async fn good_spawn_lifetime(data: String) { tokio::spawn(async move { println!("{}", data); // OK: 拥有数据 }); } ``` ### 错误处理 ```rust // ❌ 生产代码中使用 unwrap/expect fn bad_parse(input: &str) -> i32 { input.parse().unwrap() // panic! } // ✅ 正确传播错误 fn good_parse(input: &str) -> Result { input.parse() } // ❌ 吞掉错误信息 fn bad_error_handling() -> Result<()> { match operation() { Ok(v) => Ok(v), Err(_) => Err(anyhow!("operation failed")) // 丢失原始错误 } } // ✅ 使用 context 添加上下文 fn good_error_handling() -> Result<()> { operation().context("failed to perform operation")?; Ok(()) } // ❌ 库代码使用 anyhow(应该用 thiserror) // lib.rs pub fn parse_config(path: &str) -> anyhow::Result { // 调用者无法区分错误类型 } // ✅ 库代码用 thiserror 定义错误类型 #[derive(Debug, thiserror::Error)] pub enum ConfigError { #[error("failed to read config file: {0}")] Io(#[from] std::io::Error), #[error("invalid config format: {0}")] Parse(#[from] serde_json::Error), } pub fn parse_config(path: &str) -> Result { // 调用者可以 match 不同错误 } // ❌ 忽略 must_use 返回值 fn bad_ignore_result() { some_fallible_operation(); // 警告:unused Result } // ✅ 显式处理或标记忽略 fn good_handle_result() { let _ = some_fallible_operation(); // 显式忽略 // 或 some_fallible_operation().ok(); // 转换为 Option } ``` ### 性能陷阱 ```rust // ❌ 不必要的 collect fn bad_process(items: &[i32]) -> i32 { items.iter() .filter(|x| **x > 0) .collect::>() // 不必要的分配 .iter() .sum() } // ✅ 惰性迭代 fn good_process(items: &[i32]) -> i32 { items.iter() .filter(|x| **x > 0) .sum() } // ❌ 循环中重复分配 fn bad_loop() -> String { let mut result = String::new(); for i in 0..1000 { result = result + &i.to_string(); // 每次迭代都重新分配! } result } // ✅ 预分配或使用 push_str fn good_loop() -> String { let mut result = String::with_capacity(4000); // 预分配 for i in 0..1000 { write!(result, "{}", i).unwrap(); // 原地追加 } result } // ❌ 过度使用 clone fn bad_clone(data: &HashMap>) -> Vec { data.get("key").cloned().unwrap_or_default() } // ✅ 返回引用或使用 Cow fn good_ref(data: &HashMap>) -> &[u8] { data.get("key").map(|v| v.as_slice()).unwrap_or(&[]) } // ❌ 大结构体按值传递 fn bad_pass(data: LargeStruct) { ... } // 拷贝整个结构体 // ✅ 传递引用 fn good_pass(data: &LargeStruct) { ... } // ❌ Box 用于小型已知类型 fn bad_trait_object() -> Box> { Box::new(vec![1, 2, 3].into_iter()) } // ✅ 使用 impl Trait fn good_impl_trait() -> impl Iterator { vec![1, 2, 3].into_iter() } // ❌ retain 比 filter+collect 慢(某些场景) vec.retain(|x| x.is_valid()); // O(n) 但常数因子大 // ✅ 如果不需要原地修改,考虑 filter let vec: Vec<_> = vec.into_iter().filter(|x| x.is_valid()).collect(); ``` ### 生命周期与引用 ```rust // ❌ 返回局部变量的引用 fn bad_return_ref() -> &str { let s = String::from("hello"); &s // Error: s will be dropped } // ✅ 返回拥有的数据或静态引用 fn good_return_owned() -> String { String::from("hello") } // ❌ 生命周期过度泛化 fn bad_lifetime<'a, 'b>(x: &'a str, y: &'b str) -> &'a str { x // 'b 没有被使用 } // ✅ 简化生命周期 fn good_lifetime(x: &str, _y: &str) -> &str { x // 编译器自动推断 } // ❌ 结构体持有多个相关引用但生命周期独立 struct Bad<'a, 'b> { name: &'a str, data: &'b [u8], // 通常应该是同一个生命周期 } // ✅ 相关数据使用相同生命周期 struct Good<'a> { name: &'a str, data: &'a [u8], } ``` ### Rust 审查清单 **所有权与借用** - [ ] clone() 是有意为之,不是绕过借用检查器 - [ ] 避免在结构体中存储借用(除非必要) - [ ] Rc/Arc 使用合理,没有隐藏不必要的共享状态 - [ ] 没有不必要的 RefCell(运行时检查 vs 编译时) **Unsafe 代码** - [ ] 每个 unsafe 块有 SAFETY 注释 - [ ] unsafe fn 有 # Safety 文档 - [ ] 安全不变量被清晰记录 - [ ] unsafe 边界尽可能小 **异步/并发** - [ ] 没有在异步上下文中阻塞 - [ ] 没有跨 .await 持有 std::sync 锁 - [ ] spawn 的任务满足 'static 约束 - [ ] Future 被正确 await 或 spawn - [ ] 锁的顺序一致(避免死锁) **错误处理** - [ ] 库代码使用 thiserror,应用代码使用 anyhow - [ ] 错误有足够的上下文信息 - [ ] 没有在生产代码中 unwrap/expect - [ ] must_use 返回值被正确处理 **性能** - [ ] 避免不必要的 collect() - [ ] 大数据结构传引用 - [ ] 字符串拼接使用 String::with_capacity 或 write! - [ ] impl Trait 优于 Box(当可能时) **类型系统** - [ ] 善用 newtype 模式增加类型安全 - [ ] 枚举穷尽匹配(没有 _ 通配符隐藏新变体) - [ ] 生命周期尽可能简化 ## SQL ### Injection Vulnerabilities ```sql -- ❌ String concatenation (SQL injection risk) query = "SELECT * FROM users WHERE id = " + user_id -- ✅ Parameterized queries query = "SELECT * FROM users WHERE id = ?" cursor.execute(query, (user_id,)) ``` ### Performance Issues - [ ] Missing indexes on filtered/joined columns - [ ] SELECT * instead of specific columns - [ ] N+1 query patterns - [ ] Missing LIMIT on large tables - [ ] Inefficient subqueries vs JOINs ### Common Mistakes - [ ] Not handling NULL comparisons correctly - [ ] Missing transactions for related operations - [ ] Incorrect JOIN types - [ ] Case sensitivity issues - [ ] Date/timezone handling errors ## API Design ### REST Issues - [ ] Inconsistent resource naming - [ ] Wrong HTTP methods (POST for idempotent operations) - [ ] Missing pagination for list endpoints - [ ] Incorrect status codes - [ ] Missing rate limiting ### Data Validation - [ ] Missing input validation - [ ] Incorrect data type validation - [ ] Missing length/range checks - [ ] Not sanitizing user input - [ ] Trusting client-side validation ## Testing ### Test Quality Issues - [ ] Testing implementation details instead of behavior - [ ] Missing edge case tests - [ ] Flaky tests (non-deterministic) - [ ] Tests with external dependencies - [ ] Missing negative tests (error cases) - [ ] Overly complex test setup