Skills Plugins MCP Prompt Model 博客 我的中心

rust-patterns

Patrones idiomáticos de Rust, ownership, manejo de errores, traits, concurrencia y buenas prácticas para construir aplicaciones seguras y eficientes.

DeepseekModel キュレーション済みスキル 品質 優秀 · 90 v1.0.0

取得

https://deepseekmodel.com/api/download.php?id=affaan-m-ecc-docs-es-skills-rust-patterns-skill-md&format=skill
ダウンロード .skill 標準形式。system_prompt と model_config を収録し、任意の Agent で利用可能
.skill ファイルの system_prompt フィールドの実際の内容。
name rust-patterns description Patrones idiomáticos de Rust, ownership, manejo de errores, traits, concurrencia y buenas prácticas para construir aplicaciones seguras y eficientes. origin ECC Patrones de Desarrollo Rust Patrones idiomáticos y buenas prácticas de Rust para construir aplicaciones seguras, eficientes y mantenibles. Cuándo Usar Escribir código Rust nuevo Revisar código Rust Refactorizar código Rust existente Diseñar la estructura de crates y la organización de módulos Cómo Funciona Este skill refuerza las convenciones idiomáticas de Rust en seis áreas clave: ownership y borrowing para prevenir data races en tiempo de compilación, propagación de errores con Result / ? usando thiserror para bibliotecas y anyhow para aplicaciones, enums y pattern matching exhaustivo para hacer imposibles los estados inválidos, traits y genéricos para abstracciones de costo cero, concurrencia segura con Arc<Mutex<T>> , canales y async/await, y superficies pub mínimas organizadas por dominio. Principios Fundamentales 1. Ownership y Borrowing El sistema de ownership de Rust previene data races y bugs de memoria en tiempo de compilación. // Bien: Pasar referencias cuando no se necesita el ownership fn process (data: &[ u8 ]) -> usize { data. len () } // Bien: Tomar ownership solo cuando se necesita almacenar o consumir fn store (data: Vec < u8 >) -> Record { Record { payload: data } } // Mal: Clonar innecesariamente para evitar el borrow checker fn process_bad (data: & Vec < u8 >) -> usize { let cloned = data. clone (); // Costoso — solo tomar prestado cloned. len () } Usar Cow para Ownership Flexible use std::borrow::Cow; fn normalize (input: & str ) -> Cow< '_ , str > { if input. contains ( ' ' ) { Cow:: Owned (input. replace ( ' ' , "_" )) } else { Cow:: Borrowed (input) // Costo cero cuando no se necesita mutación } } Manejo de Errores Usar Result y ? — Nunca unwrap() en Producción // Bien: Propagar errores con contexto use anyhow::{Context, Result }; fn load_config (path: & str ) -> Result <Config> { let content = std::fs:: read_to_string (path) . with_context (|| format! ( "failed to read config from {path}" ))?; let config : Config = toml:: from_str (&content) . with_context (|| format! ( "failed to parse config from {path}" ))?; Ok (config) } // Mal: Causa panic en caso de error fn load_config_bad (path: & str ) -> Config { let content = std::fs:: read_to_string (path). unwrap (); // ¡Panic! toml:: from_str (&content). unwrap () } Errores de Biblioteca con thiserror , Errores de Aplicación con anyhow // Código de biblioteca: errores estructurados y tipados use thiserror::Error; #[derive(Debug, Error)] pub enum StorageError { #[error( "record not found: {id}" )] NotFound { id: String }, #[error( "connection failed" )] Connection ( #[from] std::io::Error), #[error( "invalid data: {0}" )] InvalidData ( String ), } // Código de aplicación: manejo de errores flexible use anyhow::{bail, Result }; fn run () -> Result <()> { let config = load_config ( "app.toml" )?; if config.workers == 0 { bail!( "worker count must be > 0" ); } Ok (()) } Combinadores de Option en Lugar de Matching Anidado // Bien: Cadena de combinadores fn find_user_email (users: &[User], id: u64 ) -> Option < String > { users. iter () . find (|u| u.id == id) . map (|u| u.email. clone ()) } // Mal: Matching profundamente anidado fn find_user_email_bad (users: &[User], id: u64 ) -> Option < String > { match users. iter (). find (|u| u.id == id) { Some (user) => match &user.email { email => Some (email. clone ()), }, None => None , } } Enums y Pattern Matching Modelar Estados con Enums // Bien: Los estados imposibles son irrepresentables enum ConnectionState { Disconnected, Connecting { attempt: u32 }, Connected { session_id: String }, Failed { reason: String , retries: u32 }, } fn handle (state: &ConnectionState) { match state { ConnectionState::Disconnected => connect (), ConnectionState::Connecting { attempt } if *attempt > 3 => abort (), ConnectionState::Connecting { .. } => wait (), ConnectionState::Connected { session_id } => use_session (session_id), ConnectionState::Failed { retries, .. } if *retries < 5 => retry (), ConnectionState::Failed { reason, .. } => log_failure (reason), } } Matching Exhaustivo — Sin Comodín en Lógica de Negocio // Bien: Manejar cada variante explícitamente match command { Command::Start => start_service (), Command::Stop => stop_service (), Command::Restart => restart_service (), // Agregar una nueva variante fuerza su manejo aquí } // Mal: El comodín oculta nuevas variantes match command { Command::Start => start_service (), _ => {} // Ignora silenciosamente Stop, Restart y variantes futuras } Traits y Genéricos Aceptar Genéricos, Retornar Tipos Concretos // Bien: Entrada genérica, salida concreta fn read_all (reader: & mut impl Read ) -> std::io:: Result < Vec < u8 >> { let mut buf = Vec :: new (); reader. read_to_end (& mut buf)?; Ok (buf) } // Bien: Bounds de traits para múltiples restricciones fn process <T: Display + Send + 'static >(item: T) -> String { format! ( "processed: {item}" ) } Trait Objects para Dispatch Dinámico // Usar cuando se necesitan colecciones heterogéneas o sistemas de plugins trait Handler : Send + Sync { fn handle (& self , request: &Request) -> Response; } struct Router { handlers: Vec < Box < dyn Handler>>, } // Usar genéricos cuando se necesita rendimiento (monomorfización) fn fast_process <H: Handler>(handler: &H, request: &Request) -> Response { handler. handle (request) } Patrón Newtype para Seguridad de Tipos // Bien: Tipos distintos previenen mezclar argumentos struct UserId ( u64 ); struct OrderId ( u64 ); fn get_order (user: UserId, order: OrderId) -> Result <Order> { // No se pueden intercambiar accidentalmente user ID y order ID todo!() } // Mal: Fácil intercambiar argumentos fn get_order_bad (user_id: u64 , order_id: u64 ) -> Result <Order> { todo!() } Structs y Modelado de Datos Patrón Builder para Construcción Compleja struct ServerConfig { host: String , port: u16 , max_connections: usize , } impl ServerConfig { fn builder (host: impl Into < String >, port: u16 ) -> ServerConfigBuilder { ServerConfigBuilder { host: host. into (), port, max_connections: 100 } } } struct ServerConfigBuilder { host: String , port: u16 , max_connections: usize } impl ServerConfigBuilder { fn max_connections ( mut self , n: usize ) -> Self { self .max_connections = n; self } fn build ( self ) -> ServerConfig { ServerConfig { host: self .host, port: self .port, max_connections: self .max_connections } } } // Uso: ServerConfig::builder("localhost", 8080).max_connections(200).build() Iteradores y Closures Preferir Cadenas de Iteradores sobre Bucles Manuales // Bien: Declarativo, lazy, composable let active_emails : Vec < String > = users. iter () . filter (|u| u.is_active) . map (|u| u.email. clone ()) . collect (); // Mal: Acumulación imperativa let mut active_emails = Vec :: new (); for user in &users { if user.is_active { active_emails. push (user.email. clone ()); } } Usar collect() con Anotación de Tipo // Recolectar en diferentes tipos let names : Vec <_> = items. iter (). map (|i| &i.name). collect (); let lookup : HashMap<_, _> = items. iter (). map (|i| (i.id, i)). collect (); let combined : String = parts. iter (). copied (). collect (); // Recolectar Results — cortocircuita al primer error let parsed : Result < Vec < i32 >, _> = strings. iter (). map (|s| s. parse ()). collect (); Concurrencia Arc<Mutex<T>> para Estado Mutable Compartido use std::sync::{Arc, Mutex}; let counter = Arc:: new (Mutex:: new ( 0 )); let handles : Vec <_> = ( 0 .. 10 ). map (|_| { let counter = Arc:: clone (&counter); std::thread:: spawn ( move || { let mut num = counter. lock (). expect ( "mutex poisoned" ); *num += 1 ; }) }). collect (); for handle in handles { handle. join (). expect ( "worker thread panicked" ); } Canales para Paso de Mensajes use std::sync::mpsc; let (tx, rx) = mpsc:: sync_channel ( 16 ); // Canal acotado con backpressure for i in 0 .. 5 { let tx = tx. clone (); std::thread:: spawn ( move || { tx. send ( format! ( "message {i}" )). expect ( "receiver disconnected" ); }); } drop (tx); // Cerrar el sender para que el iterador rx termine for msg in rx { println! ( "{msg}" ); } Async con Tokio use tokio::time::Duration; async fn fetch_with_timeout (url: & str ) -> Result < String > { let response = tokio::time:: timeout ( Duration:: from_secs ( 5 ), reqwest:: get (url), ) . await . context ( "request timed out" )? . context ( "request failed" )?; response. text (). await . context ( "failed to read body" ) } // Lanzar tareas concurrentes async fn fetch_all (urls: Vec < String >) -> Vec < Result < String >> { let handles : Vec <_> = urls. into_iter () . map (|url| tokio:: spawn ( async move { fetch_with_timeout (&url). await })) . collect (); let mut results = Vec :: with_capacity (handles. len ()); for handle in handles { results. push (handle. await . unwrap_or_else (|e| panic! ( "spawned task panicked: {e}" ))); } results } Código Unsafe Cuándo Unsafe Es Aceptable // Aceptable: Frontera FFI con invariantes documentados (Rust 2024+) /// # Safety /// `ptr` must be a valid, aligned pointer to an initialized `Widget`. unsafe fn widget_from_raw < 'a >(ptr: * const Widget) -> & 'a Widget { // SAFETY: el llamador garantiza que ptr es válido y alineado unsafe { &*ptr } } // Aceptable: Ruta crítica de rendimiento con prueba de corrección // SAFETY: index is always < len due to the loop bound unsafe { slice. get_unchecked (index) } Cuándo Unsafe NO Es Aceptable // Mal: Usar unsafe para evadir el borrow checker // Mal: Usar unsafe por conveniencia // Mal: Usar unsafe sin un comentario Safety // Mal: Hacer transmute entre tipos no relacionados Sistema de Módulos y Estructura de Crates Organizar por Dominio, No por Tipo my_app/ ├── src/ │ ├── main.rs │ ├── lib.rs │ ├── auth/ # Módulo de dominio │ │ ├── mod.rs │ │ ├── token.rs │ │ └── middleware.rs │ ├── orders/ # Módulo de dominio │ │ ├── mod.rs │ │ ├── model.rs │ │ └── service.rs │ └── db/ # Infraestructura │ ├── mod.rs │ └── pool.rs ├── tests/ # Pruebas de integración ├── benches/ # Benchmarks └── Cargo.toml Visibilidad — Exponer el Mínimo // Bien: pub(crate) para compartir internamente
このスキルを起動するキーワード。クリックでコピーできます。

このスキルにはトリガーワードがありません。

ダウンロードした .skill に含まれるフィールド。
フィールド 説明
formatフォーマット識別子(skill/v1)
skill_idスキル固有 ID
nameスキル名
versionバージョン
description説明
categoryカテゴリ(配列)
trigger_wordsトリガーワード
tagsタグ
sourceソース
source_urlソース URL(本ページ)
exported_atエクスポート日時(ダウンロード毎)
system_promptシステムプロンプト本文
model_configモデル設定:provider / model / temperature / max_tokens / top_p
examplesサンプル
install_guide各プラットフォームの導入説明(Coze / Dify / Claude / カスタム)
同じスキルを各プラットフォーム形式で出力できます。
.skill 標準形式。system_prompt と model_config を収録し、任意の Agent で利用可能 ダウンロード
.skillpro 拡張形式。scripts / tools / dependencies / hooks を含む ダウンロード
.json 純粋な JSON 出力。system_prompt とモデル設定のみ ダウンロード
Coze frontmatter 付き Markdown。Coze へのインポート用 ダウンロード
Dify Dify DSL。アプリ作成後にそのままインポート ダウンロード

每日精选 Skill 推荐,免费送到你邮箱

输入邮箱,每天接收一个精选 AI Agent 技能推荐。完全免费,持续更新。

验证码 --

提交后我们会发送一封确认邮件,点击邮件里的链接才会开始收信。

完全免费,取消任意时间。我们不会发送垃圾邮件。