GAP·MAP
← all breakdowns
RustOwnershipString SlicesUTF-8junior level

Owned Strings and Borrowed String Slices

the question

What is the difference between `String`, `str`, and `&str` in Rust? When would you use each one?

what they're testing: The interviewer is checking whether you can connect Rust's ownership and borrowing model to practical API design.

a strong answer

String owns its text, str is the string slice type itself, and &str is the usual borrowed view of a string slice. A String stores valid UTF-8 bytes in a growable heap buffer and tracks a pointer, length, and capacity. With mutable access, it can append, remove, and reallocate as it grows.

A bare str is dynamically sized, so code normally uses it behind a pointer such as &str or Box<str>. An &str contains a pointer and byte length. It can view all or part of a String, a string literal, or other valid UTF-8 data without copying the bytes. The reference cannot outlive the data it borrows.

For a function input that only needs to read text, prefer &str. Callers can pass a literal, a substring, or a borrowed String; deref coercion converts &String to &str in suitable contexts. Use String when a function or struct must own the text independently of the caller, or when it needs a growable string. Both String and str hold valid UTF-8, so byte offsets are not character positions. Range slicing panics if the range is reversed, out of bounds, or cuts through a UTF-8 code point.

Where people slip

the tempting wrong answer, and what's actually true

  • `String` is the mutable string type and `str` is the immutable string type.

    Mutability is not the type distinction. `String` owns a growable buffer and can be borrowed immutably, while `str` is an unsized slice that can also be borrowed as `&mut str` for in-place changes.

  • An `&str` always borrows from a `String` on the heap.

    An `&str` can borrow from a `String`, a string literal in the program binary, or valid UTF-8 bytes stored elsewhere, including a stack array.

  • Passing `&str` creates a new copy of the string data.

    An `&str` is a borrowed pointer-and-length view, so borrowing one does not copy the underlying text.

  • A `String` is an array of Unicode characters, so any numeric index is a valid character boundary.

    Rust does not support indexing a string with one number to get a character. String ranges use byte offsets, and range indexing panics if an offset is out of bounds or falls inside a multibyte code point.

If they push further

Why should a read-only function parameter usually be `&str` instead of `&String`?

`&str` accepts borrowed `String` data, literals, and substrings, so it gives callers more flexibility without taking ownership or allocating.

How do you convert between `String` and `&str`?

Borrow a `String` as `&str` with `s.as_str()` or rely on deref coercion in a suitable context. Create an owned `String` from `&str` with `to_owned()`, `to_string()`, or `String::from`, which copies the text into owned storage.

Why can slicing a Rust string panic?

String ranges use byte offsets, but every boundary must also be a UTF-8 code point boundary. Use methods such as `get` when invalid ranges should return `None` instead of panicking.

Sources

Now answer it yourself.

Reading a strong answer is easy. Producing one under pressure is the skill the interview tests. Gapmap grades your answer against the same bar an interviewer would.

was this useful?

beta

The interviewer part is in the works.

The diagnostic, personal maps, and AI mock interviews are being finished right now. The notes stay free either way. Leave an email and you'll get the first-cohort invite, plus a month of Pro when it opens.