June 2025
Soy un novato en Rust. Aprendí porque algunos clientes querían ejecutar Rust en React-Native. Por eso he estado aprendiendo sobre la marcha y confiando en copilot para enseñarme los conceptos básicos. Pero los LLMs son máquinas de regurgitar y no siempre dan el código más idiomático. Aquí algunos consejos que he aprendido. Con sus matices, claro: asume que puedes usar std
, etc.
No uses los crates lazy_static
o once_cell
, su funcionalidad ya está incorporada en la librería estándar (std
) y ahora puedes usar OnceLock
y LazyLock
para inicializar variables globales.
// ❌ No hagas esto
lazy_static! {
// tus variables globales
}
// ✅ Haz esto
static MY_GLOBAL_STRING: LazyLock<RwLock<String>> =
LazyLock::new(|| RwLock::new("Hello World!".into()));
Generalmente, RwLock
es lo que quieres en vez de Mutex
. Permite múltiples lectores sin bloquear completamente tu proceso. Eso sí, si vas a leer y escribir en la misma función, ¡es muy importante liberar cualquier lock de lectura!
let my_read_var = MY_VAR.read().unwrap()
// Si no haces drop
drop(my_read_var)
// Este writer se bloqueará
let mut my_write_var = MY_VAR.write().unwrap();
cfg
s para evitar traits async, uso de send+sync, etc.Si expones una API en C y devuelves std::ffi::Cstring
, las cadenas deben ser devueltas a Rust para ser liberadas de forma segura.
#[no_mangle]
unsafe extern "C" fn get_a_string() -> *mut c_char {
let data = CString::new("Hello World!".into()).unwrap();
data.into_raw() as *mut c_char
}
// El puntero debe ser devuelto a Rust para su liberación segura
#[no_mangle]
unsafe extern "C" fn free_string(ptr: *mut c_char) {
if ptr.is_null() {
return;
}
let _ = CString::from_raw(ptr);
// Se libera automáticamente al final de la función
}
Result
y Option
. Permiten un código Rust muy idiomático y conciso. Fomenta su uso.nativetls
y rustls
. Si apuntas a multiplataforma, usa rustls
si es posible.Ring
está siendo deprecado/abandonado, muchas librerías están migrando a aws-lc-rs
, tú también deberías.
#[cfg(test)]
o #[cfg(debug)]
, pero esto puede causar problemas a futuro con errores ocultos que no se detectan durante el desarrollo. He visto que usar if cfg!(test)
a veces es mejor, ya que todas las ramas del código se compilan y se evitan zonas muertas de compilación que pueden esconder problemas más profundos.?
parece ser la forma recomendada, pero ¿se pierde la línea exacta donde ocurrió el error? No estoy seguro si lo estoy haciendo mal. En todo caso, es mejor usarlo con tipos de error muy específicos.assert2
es genial y hará que tus tests sean más fáciles de depurar mostrando los valores con colores, en vez de solo errores opacos.