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 Curated skill Quality Excellent · 90 v1.0.0

Get

https://deepseekmodel.com/api/download.php?id=affaan-m-ecc-docs-es-skills-rust-patterns-skill-md&format=skill
Download .skill Standard format with system_prompt and model_config, ready for any agent framework
The actual content of the system_prompt field in the .skill file.
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
Keywords that activate this skill. Click one to copy it.

This skill does not provide trigger words.

The downloaded .skill package contains the following fields.
Field Description
formatFormat tag (skill/v1)
skill_idUnique skill ID
nameSkill name
versionVersion
descriptionDescription
categoryCategories (array)
trigger_wordsTrigger words
tagsTags
sourceSource
source_urlSource URL (this page)
exported_atExported at (set per download)
system_promptSystem prompt body
model_configModel config: provider / model / temperature / max_tokens / top_p
examplesExamples
install_guideImport guide for Coze / Dify / Claude / custom frameworks
The same skill can be exported in different platform formats.
.skill Standard format with system_prompt and model_config, ready for any agent framework Download
.skillpro Enhanced format with scripts, tools, dependencies and hooks Download
.json Plain JSON export with system_prompt and model parameters only Download
Coze Markdown with frontmatter, for Coze platform import Download
Dify Dify DSL, import directly after creating an app Download

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

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

验证码 --

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

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