Rust: String vs str
Tags: rust
Published: 2020-10-08 13:23:32

In this blog post, let's explore key differences between String and str and when to use what.

`String` is a heap-allocated, growable data structure.
`str` is an immutable, fixed-length sequence of characters stored in memory (heap/stack).

#### String

A String can be created either using `String::from` method or `.to_string()` method as below:

```rust
    // Creating new String variable s1 using String::from method
    let mut s1: String = String::from("Sivakumar");
    println!("{}", s1);
    
    // Creating new String variable s2 using to_string() method
    let s2: String = "Sivakumar".to_string();
    println!("{}", s2);
    
    // Calling len() and capacity() methods on string variable
    println!("s1 variable's Length: {}, Capacity: {}", s1.len(), s1.capacity());
    
    // Calling len() and capacity() methods on string variable
    println!("s2 variable's Length: {}, Capacity: {}", s2.len(), s2.capacity());
    
    // Adding more data to existing string variable
    s1.push_str(" is working in Singapore!!!");
    println!("{}", s1);
```

When we run the above code, we'll get following output:

```rust
Sivakumar
Sivakumar
s1 variable's Length: 9, Capacity: 9
s2 variable's Length: 9, Capacity: 9
Sivakumar is working in Singapore!!!
```

#### str

str variable can be created just by declaring a string literal as below and it will always be immutable.

```rust
    // str typed variable can be created as below
    let str1 = "Sivakumar";
    println!("{}", str1);
    
    // Calling len() method on str variable
    println!("str1 variable's Length: {}", str1.len());
```

When we run the above code, we'll get following output:

```rust
Sivakumar
s1 variable's Length: 9
```

If you notice above, rust won't allow you to declare str variable with its specific type. Instead, rust will infer the data type for you.

And also, there is no `capacity()` method available on str variable. 

If you try to declare str as mutable, you'll end up getting warning as below

```rust
    // str typed variable can be created as below
    let mut str1 = "Sivakumar";
    println!("{}", str1);
    
    // Calling len() method on str variable
    println!("str1 variable's Length: {}", str1.len());

warning: variable does not need to be mutable
  --> src\main.rs:23:9
   |
23 |     let mut str1 = "Sivakumar";
   |         ----^^^^
   |         |
   |         help: remove this `mut`
   |
   = note: `#[warn(unused_mut)]` on by default

warning: 1 warning emitted

    Finished dev [unoptimized + debuginfo] target(s) in 0.88s
     Running `target\debug\example.exe`
Sivakumar
str1 variable's Length: 9
```

When we have a function which accepts slice of characters, you can pass `String` referenced variable as an argument.

```rust
fn print_len(s: &str) {
    println!("Length of variable: {}", s.len());
}

    // str typed variable can be created as below
    let str1 = "Sivakumar";
    println!("{}", str1);
    
    // Creating new String variable s1 using String::from method
    let s1: String = String::from("Sivakumar");
    println!("{}", s1);
    
    print_len(str1);
    
    print_len(&s1);
``` 

When you run the above code, you will get following output:

```rust
Sivakumar
Sivakumar
Length of variable: 9
Length of variable: 9
```

But, when you have a method which accepts, `String` as argument, passing `str` variable will result in compiler error

```rust
fn print_len(s: String) {
    println!("Length of variable: {}", s.len());
}

    // str typed variable can be created as below
    let str1 = "Sivakumar";
    println!("{}", str1);
    
    // Creating new String variable s1 using String::from method
    let s1: String = String::from("Sivakumar");
    println!("{}", s1);
    
    print_len(str1);
    
    print_len(s1);
``` 

Output:

```rust
error[E0308]: mismatched types
  --> src\main.rs:34:15
   |
34 |     print_len(str1);
   |               ^^^^
   |               |
   |               expected struct `std::string::String`, found `&str`
   |               help: try using a conversion method: `str1.to_string()`

error[E0308]: mismatched types
  --> src\main.rs:36:15
   |
36 |     print_len(&s1);
   |               ^^^
   |               |
   |               expected struct `std::string::String`, found `&std::string::String`
   |               help: consider removing the borrow: `s1`

error: aborting due to 2 previous errors

For more information about this error, try `rustc --explain E0308`.
error: could not compile `example`.

To learn more, run the command again with --verbose.

```

Please feel free to share your comments.

Happy reading!!!