str::get¶
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.
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_mut— the mutable versionstr::split_at_checked— the same safety for a single cut pointstr::is_char_boundary— telling the two failures apartstr::chars— when you wanted a character, not a range
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