This post shows how to modify a struct instance in a function. It uses the mutable shared borrowing to pass a mutable reference as an argument to a function.
Struct And Instance
Consider the following Person struct. It has two fields – name and email – of String type.
1 2 3 4 | struct Person { name: String, email: String } |
To create an instance of this struct, we use the struct expression and assign it to a mutable variable. A mutable variable uses the mut keyword between the let keyword and the variable name.
1 2 3 4 | let mut person_1 = Person { name: "Matt".to_string(), email: "matt@email.com".to_string() }; |
At this point, we have an instance whose content we can modify anywhere in the same code block. If we want to modify it within a function, we need to define a function accordingly.
Modify In A Function
When we want to modify a struct instance passed as an argument to a function, we need to define the function parameter prefixed with &mut and space. Moreover, we need to prefix the argument with &mut and space when invoking the function. Consider the following function.
1 2 3 4 | fn update_name_and_email(person: &mut Person) { person.name = "matthew".to_string(); person.email = "matthew@email.com".to_string(); } |
Notice the codes used &mut Person for the person parameter.
Pass Struct Instance To Function
Now, we invoke the function with a mutable reference to the struct instance.
1 2 3 | println!("Before: {} {} ", person_1.name, person_1.email); update_name_and_email(&mut person_1); println!("After: {} {} ", person_1.name, person_1.email); |
Notice the codes used &mut person_1 as the argument. The codes output the following.
1 2 | Before: Matt matt@email.com After: matthew matthew@email.com |
Complete Rust Codes
In summary, we pass a mutable reference as an argument to a function. There are three points to remember. First, create a mutable instance of a struct using the mut keyword. Second, create a function with a parameter definition of param_name &mut [struct-type] as an argument to a function. Third, pass the reference of the mutable instance prefixed with &mut and space. The following is the complete source code file.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | struct Person { name: String, email: String } fn main() { let mut person_1 = Person { name: "Matt".to_string(), email: "matt@email.com".to_string() }; println!("Before: {} {} ", person_1.name, person_1.email); update_name_and_email(&mut person_1); println!("After: {} {} ", person_1.name, person_1.email); } fn update_name_and_email(person: &mut Person) { person.name = "matthew".to_string(); person.email = "matthew@email.com".to_string(); } |
When we don’t want to modify a struct instance in a function, we omit all the mut keywords used. We change the update_name_and_email function and the way other codes call it, as shown below.
1 2 3 4 5 | fn update_name_and_email(person: &Person) { // NOTE: The lines below were commented out. They'll cause compile-time errors // person.name = "matthew".to_string(); // person.email = "matthew@email.com".to_string(); } |
We run the function as follows.
1 2 3 | println!("Before: {} {} ", person_1.name, person_1.email); update_name_and_email(&person_1); println!("After: {} {} ", person_1.name, person_1.email); |
We used Rust 1.42.0 for this post.