Defining and using Structs
You can define a struct using the struct
keyword followed by the name of the struct and a block of curly braces. Inside the block, you define the fields of the struct. Each field has a name and a type, different fields in a struct can have different types.
Let's get started, run the following command to create a new Rust project:
Let's define a struct named User
with three fields: id
, username
, and email
. The id
field is of type i32
, and the username
and email
fields are of type String
. Here's the code:
Creating instances of a struct
After you define a struct, you can create instances of the struct by using the struct_name { field: value, field: value }
syntax. Let's create an instance of our User
struct:
In this example, we create a new instance of the User
struct with the id
field set to 1
, the username
field set to john_doe
, and the email
field set to jon@doe.com
.
Accessing fields of a struct
You can then access the fields of a struct using the dot notation. Here's an example:
In this example, we access the id
, username
, and email
fields of the user
instance using the dot notation.
If you have variables with the same name as the fields of a struct, you can use the struct init shorthand syntax to create an instance of the struct. Here's an example:
Notice that we didn't have to specify username: username
and email: email
in this example. Rust automatically assigns the values of the username
and email
variables to the username
and email
fields of the User
struct because the variable names match the field names, this shorthand is called the struct init shorthand.
If you have another instance and want to copy some of its fields to a new instance, you can use the struct update syntax. Here's an example:
In this example, we create a new instance of the User
struct named user1
. Then, we create another instance named user2
using the struct update syntax. We specify the id
field of user2
and use the ..
syntax followed by the user1
instance to copy the username
and email
fields from user1
to user2
. This is called the struct update syntax.
Debugging structs
If you want to print the contents of a struct for debugging purposes, you can use the {:?}
format specifier with the println!
macro. Here's an example:
However, if you try to compile the code, you'll get an error:
Debugging struct error
The reason for this error is that, in order to print a value to the console, it must implement the Debug
trait. You don't need to understand traits yet, and you don't need to know how to implement them, because Rust provides us a macro that will automatically implement the Debug
trait on structs for us.
To fix this error, you can derive
macro along with the Debug
trait for the Dog
struct by adding #[derive(Debug)]
above the struct definition.
A macro
is just code that writes code. In this case, the derive
macro writes the code to implement the Debug
trait for the Dog
struct, since implementing the Debug
trait is such a common thing in Rust, we don't need to repetitively implement them manually every time we define a new struct, therefore we use the derive
macro to automatically implement them for us. Both the Debug
trait and the derive
macro are part of the Rust standard library and are part of the prelude, so you don't need to import them using the use
keyword.
Here's the updated code:
Now, if you run the code, you'll see the contents of the Dog
struct printed to the console.
Debugging a struct
The
#[derive(Debug)]
attribute is a Rust macro that automatically implements theDebug
trait for theDog
struct. This allows you to print the contents of the struct using the{:?}
format specifier.
That's not all, structs can also have methods and associated functions, we'll learn about them in the next lesson.