Introducción
Mover un String transfiere su propiedad, pero muchas funciones solo necesitan acceder a él temporalmente. Rust denomina préstamo a ese acceso temporal y lo representa mediante una referencia.
Completará un programa preparado de una lista de invitados en tres etapas breves: inspeccionará texto propio mediante una referencia compartida, observará intencionadamente por qué el acceso compartido no puede modificarlo y, después, realizará una actualización controlada mediante una referencia mutable. La salida final demostrará que main aún conserva la propiedad de la lista y puede utilizarla.
Inspeccionar datos mediante una referencia compartida
En este paso, prestará a una función acceso de solo lectura a un String en lugar de transferirle su propiedad.
Acceda al proyecto de Cargo preparado y abra su código fuente:
cd /home/labex/project/guest-borrowing
nano src/main.rs
La configuración creó el proyecto completo y dejó un marcador de posición en la llamada a inspect_guests. El tipo de su parámetro es &String. El símbolo & significa «una referencia a un String»: la función puede consultar temporalmente el valor, pero no se convierte en su propietaria.
Reemplace únicamente /* Step 1: borrow guest_list */ por &guest_list, de modo que la llamada quede así:
inspect_guests(&guest_list);
Aquí, &guest_list crea una referencia compartida. Compartida significa que se puede conceder acceso de solo lectura sin transferir el propio String.
Guarde el archivo con Ctrl+O, pulse Enter y salga con Ctrl+X. Ejecute el programa:
cargo run --quiet
La salida debe ser:
Inspecting: Ari, Bo
Caller still owns: Ari, Bo
Before update: Ari, Bo
Updated: Ari, Bo
La primera línea procede de la referencia prestada. La segunda línea demuestra algo importante sobre la propiedad: después de que inspect_guests termina, main todavía puede utilizar guest_list. La función de actualización también lee el valor actual, pero aún no lo modifica.
Observar el límite de una referencia compartida
En este paso, intentará modificar intencionadamente el String mediante una referencia compartida. El error del compilador es esperado y le proporcionará una prueba de la regla de préstamos de Rust.
Abra de nuevo el código fuente:
nano src/main.rs
Dentro de add_guest, elimine únicamente los caracteres // iniciales de la línea preparada, para que quede así:
list.push_str(", Mina");
El método push_str añade texto a un String, por lo que necesita permiso para modificar el valor. Sin embargo, list tiene actualmente el tipo &String, que concede acceso compartido y de solo lectura.
Guarde el archivo y salga. Antes de comprobarlo, prediga el resultado: el compilador debería rechazar el intento de modificación porque una referencia compartida no puede proporcionar acceso mutable.
Ejecute la comprobación. Es normal que falle:
cargo check
Busque estas partes estables del diagnóstico:
error[E0596]: cannot borrow `*list` as mutable, as it is behind a `&` reference
...
consider changing this to be a mutable reference
La expresión *list se refiere al String al que se llega mediante la referencia. Rust no está diciendo que el String nunca pueda cambiar; está indicando que esta referencia concreta &String no incluye permiso para modificarlo. En el siguiente paso concederá acceso mutable controlado.
Actualizar mediante una referencia mutable
En este paso, concederá a add_guest permiso temporal y exclusivo para modificar el String del código que realiza la llamada.
Una referencia mutable tiene la forma &mut T. Una regla útil para principiantes es muchos lectores o un escritor a la vez: las referencias compartidas permiten leer, mientras que una referencia mutable concede temporalmente acceso exclusivo de escritura. Esta exclusividad evita que dos partes del programa cambien inesperadamente el mismo valor.
Abra el archivo:
nano src/main.rs
Realice tres modificaciones concretas:
- Cambie el parámetro de
add_guestde&Stringa&mut String. - Añada
muta la declaración para que quedelet mut guest_list = .... - Cambie la llamada a
add_guestde&guest_lista&mut guest_list.
La firma completa de la función y la llamada deben tener estas formas:
fn add_guest(list: &mut String) {
add_guest(&mut guest_list);
Los dos usos de mut están relacionados, pero cumplen funciones distintas. let mut guest_list indica que el valor propio puede cambiar. Después, &mut guest_list crea una referencia mutable temporal que presta a add_guest acceso exclusivo de escritura durante la llamada.
Guarde el archivo y salga. Después, compruebe la corrección:
cargo check
Un resultado Finished sin E0596 significa que los permisos ahora son coherentes. Ejecute el programa:
cargo run --quiet
La salida final debe ser:
Inspecting: Ari, Bo
Caller still owns: Ari, Bo
Before update: Ari, Bo
Updated: Ari, Bo, Mina
El préstamo mutable termina cuando add_guest devuelve el control. La impresión final puede volver a leer guest_list, lo que demuestra que main conservó la propiedad mientras la función realizaba una actualización controlada.
Resumen
Utilizó &String para obtener acceso compartido y de solo lectura, y &mut String para realizar una modificación temporal y exclusiva. En ambos casos, el código que realiza la llamada conservó la propiedad, y el compilador ayudó a hacer cumplir la diferencia entre consultar y modificar datos prestados.



