13 Октября 2017 • оригинал: Ameya • перевод: Norman Ritchie • обучение • поддержите на Patreon

Будучи новичком в Rust, я запутывался в различных способах представления строк. В книге о языке Rust есть глава «References and Borrowing», в которой используется три различных типа строковых переменных в примерах: String , &String и &str .

Начнём с разницы между str и String : String — это расширяемая, выделяемая на куче структура данных, тогда как str — это неизменяемая строка фиксированной длины, где-то в памяти.

String

Если вы программируете на Java, String в Rust семантически эквивалентен StringBuffer (вероятно это являлось причиной моего замешательства, поскольку я привык приравнивать String с неизменяемостью). Таким образом, String имеет длину и вместимость, тогда как str имеет только один метод len() . В качестве примера:

1 2 3 4 5 6 7 8 9 10 11 let mut s = String :: from ( "Привет, Rust!" ); println! ( "{}" , s .capacity ()); // напечатает 19 s .push_str ( "Вот и я!" ); println! ( "{}" , s .len ()); // напечатает 32 let s = "Привет, Rust!" ; // ошибка компиляции: для типа `str` не найден // метод с именем `capacity`. println! ( "{}" , s .capacity ()); println! ( "{}" , s .len ()); // напечатает 19

& str

Вы можете взаимодействовать с str в качестве заимствованного типа &str . Это называется строковый срез (слайс), неизменяемое представление строки. Как мы увидим, этот способ является предпочтительным для передачи строк.

& String

Это ссылка на String , которая также является заимствованным типом. Это не более чем указатель, который вы можете передать, не передавая владение. Получается, что &String можно привести к &str :

1 2 3 4 5 6 7 8 fn main () { let s = String :: from ( "Привет, Rust!" ); foo ( & s ); } fn foo ( s : & str ) { println! ( "{}" , s ); }

В приведённом выше примере, foo() может принимать любой строковый срез (слайс) или заимствованный String , что очень удобно. Таким образом, вам почти никогда не надо иметь дело со &String . Единственный случай применения, который приходит мне в голову — если вы хотите передать изменяемую ссылку в функцию, которая должна изменить строку:

1 2 3 4 5 6 7 8 9 fn main () { let mut s = String :: from ( "Привет, Rust!" ); foo ( & mut s ); } fn foo ( s : & mut String ) { s .push_str ( "добавим foo.." ); println! ( "{}" , s ); }

Подводя итог

Предпочитайте &str , чтобы передать параметр в функцию или если вам нужно неизменяемое представление строки. А String , когда вы хотите владеть и изменять строку.