Skip to content

str::get

str methods · Strings

Level: reference · for working programmers

One line: Slicing that returns Option instead of panicking — s.get(0..5) where &s[0..5] would bring the program down.

pub const fn get<I: SliceIndex<str>>(&self, i: I) -> Option<&I::Output>

Stable since 1.20.0. Usable in a const context.

&s[a..b] has exactly two failure modes and both are run-time panics: the range is out of bounds, or an endpoint lands inside a multi-byte character. get turns both into None.

That makes it the right default for any range that came from outside your program — a byte count from a protocol, a column width, an offset stored in a file.

Note what it is not: there is no s.get(0) returning a character. The index must be a range, because str does not implement Index<usize> — a single byte of UTF-8 is not meaningful on its own, and returning one would be a bug factory. To get one character use chars; to get one byte use as_bytes.

None does not say which failure occurred. is_char_boundary and len tell you apart when it matters.

Example

str_get.rs in full — pasted here by tools/run_examples.py from the file CI compiles and runs.

fn main() {
    let s = "héllo";

    println!("{:?}", s.get(0..1));
    println!("{:?}", s.get(0..2));     // None: byte 2 is inside 'é'
    println!("{:?}", s.get(0..99));    // None: out of bounds
    println!("{:?}", s.get(..));
    println!("{:?}", s.get(3..));

    // Every range form works.
    println!("{:?} {:?} {:?}", s.get(..3), s.get(1..3), s.get(1..=2));

    // The panicking equivalents, side by side.
    println!("{:?}", &s[0..1]);
    println!("panics instead: {}", s.get(0..2).is_none());

    // There is no s.get(0) -> char. These are the two real questions.
    println!("{:?}", s.chars().next());
    println!("{:?}", s.as_bytes().first());
}

Verified output of str_get.rs — regenerated by tools/run_examples.py, never hand-typed.

Some("h")
None
None
Some("héllo")
Some("llo")
Some("hé") Some("é") Some("é")
"h"
panics instead: true
Some('h')
Some(104)

See also

str::get in the standard library ↗

Po polsku

Dla polskiego tekstu get przestaje być wariantem &s[a..b] „dla ostrożnych” i staje się domyślnym narzędziem, bo indeksy w str liczą bajty, nie litery: w „żółw” bajt numer 1 wypada w środku ż, więc &s[0..1] kładzie program paniką, a s.get(0..1) grzecznie zwraca None. Obie możliwe wpadki — wyjście poza zakres i trafienie w środek znaku wielobajtowego — get zamienia w to samo None, co jest wygodne, ale znaczy też, że samo None nie mówi, która z nich zaszła; od odróżniania są is_char_boundary() i len(). Nie ma natomiast s.get(0) zwracającego znak i nie jest to przeoczenie: str nie implementuje Index<usize>, bo pojedynczy bajt polskiej litery to pół litery. Jeśli przychodzisz z Pythona, gdzie s[0] daje znak, to właśnie tę różnicę trzeba sobie przestawić — po znak sięgasz przez chars(), po bajt przez as_bytes().

Szukaj po polsku: indeksowanie łańcucha po bajtach · granica znaku · wycinek łańcucha · rust str get vs index panic · rust byte index not char index