일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- spring boot
- Elasticsearch
- Spring
- 알고리즘
- Java
- 애자일기법
- 애자일
- 백준
- 스프링
- 엘라스틱서치
- API
- 개발
- 코드
- JPA
- 프레임워크
- 애자일프로그래밍
- 그리디알고리즘
- 자바
- cleancode
- 코딩테스트
- 그리디
- 데이터베이스
- ES
- database
- 클린코드
- 개발자
- 읽기쉬운코드
- framework
- Baekjoon
- 코딩
- Today
- Total
튼튼발자 개발 성장기🏋️
러스트 12 - 슬라이스 타입 본문
소유권을 갖지 않는 테이터 타입은 또 있다. 바로 "Slice"
슬라이스를 사용하게 된다면 Collection의 전체가 아닌 연속된 요소(Element) Sequence를 참조 할 수 있게 된다.
String에서 첫 단어를 찾는 코드를 보자.
fn main() {
let string_slice = String::from("String Slice");
let idx = get_index(&string_slice);
println!("idx : {}", idx);
}
fn get_index(str: &String) -> usize { // 소유권 X
let str_bytes = str.as_bytes(); // 들어온 str의 바이트를 겟!
// enumerate : iterator의 결과 값을 직접 반환 (튜플로)
// i : index
// item : element에 대한 참조 값
for (i, &item) in str_bytes.iter().enumerate() {
if item == b' ' { // 바이트 리터럴 구문을 사용하여 공백을 나타내는 바이트 검색
return i; // 공백이면 해당 index 반환
}
}
str.len() // 공백이 없으면 str 길이를 반환
}
"String"이라는 단어와 "Slice"라는 단어를 이어서 만든 문자열에서 첫 단어 "String"만을 알고 싶을 때, 공백의 index를 반환해주는 함수가 있다.
만일, index를 무리 없이 잘 반환이 되었다고 치자. 그 뒤에 string_slice의 값이 변경이 되었는지, 초기화 되었는지 어떻게 보장할 것인가?
코드가 서너줄이라면 뭐 그냥저냥 쓰겠지만.. 덩치가 크면 클 수록 보장을 해주어야 한다.(주석보다 확실하게...?)
index 관련 오류는 쉽게 찾을 수 있지 않다... 물론 내가 경험이 많지는 않지만 어디서 index exception이 났는지는 바로 인지가 가능하지만, 도대체 어떻게 index가 비워졌는지 혹은 추가 되었는지, 왜 이렇게 되었는지 코드를 보는데 시간이 꽤 걸린다...
이러한 문제를 해결해줄 녀석이 "스트링 슬라이스(String Slice)"라고 한다.
스트링 슬라이스는 String의 일부에 대한 참조자라고 할 수 있다.
fn main() {
let string_slice = String::from("String Slice");
let str = &string_slice[0..6];
let slice = &string_slice[7..12];
println!("first word : [{}]", str);
println!("second word : [{}]", slice);
}
"&string_slice[0..6]" 부분을 해석해보면 다음과 같다.
"string_slice의 0부터 (6-1)까지(일부만) 참조 하겠다."라고 볼 수 있다.
rust docs에 보면 [start..end] -> start부터 end를 포함하지 않는 연속된 범위러고 정의되어 있으니...같은 말이지요.
"0부터 x까지 참조하겠다!"라고 한다면 0은 생략 가능하다. ( [..x] ) : 반대로 [x,,]은 끝에 마지막 바이트까지 포함.
처음과 끝의 모든 바이트를 참조하겠다라면 [..]도 가능하다. (사용하진 않을 것같은 냄새가 난다..ㅋㅋㅋㅋㅋ)
그럼 이번 포스팅에서 배운 스트링 슬라이스를 상요해서 반환하는 함수를 만들어보자.
fn main() {
let string_slice = String::from("String Slice");
let word = get_word(&string_slice);
println!("first word : {}", word);
}
fn get_word(str: &String) -> &str { // 문자열 반환
let str_bytes = str.as_bytes(); // str 바이트 겟.
for (i, &item) in str_bytes.iter().enumerate() {
if item == b' ' { // 바이트 구분
return &str[0..i];
}
}
&str[..]
}
문자열을 반환하는 함수 get_word는 공백을 발견하면 그 즉시 처음부터 공백까지 스트링 슬라이스로 부분 참조를 시도하여 반환한다.
추가로 한가지 더 정의된 내용이 있다.
string 리터럴은 "슬라이스"다.
string 리터럴의 경우, binary 내부에 저장된다.
let string_slice = "string slice";
// string_slice 의 타입은 "&str"이다. 이것은 binary의 특정 포인터를 가르키는 슬라이스라는 것.
// string 리터럴이 불변인 이유라는 것.
...
fn get_word(str: &str) -> &str {}
// String과 &str 둘 모두에 대 한 같은 함수를 사용한다는 것. (같은 녀석이고 다르게 쓴다고 이해하면 될 듯...)
스트링 슬라이스에 대한 내용이 상당히 심오하다... 처음 보는 녀석이라 그런지 소유권부터 시작해서 심상치가 않다..
소유권 / borrowing / slice의 개념은 compile time에 메모리를 보다 더 안전하게 사용할 수 있는 녀석들이다.
rust는 다른 시스템 프로그래밍 언어와 같은 방식으로 메모리 사용을 제어한다. 그러나 소유권에 의해 자신의 scope를 벗어나면 메모리를 자동으로 반환하여 따로 디버깅이 필요가 없어진다. 단... 이러한 것들을 완벽하게 이해하고 자유롭게 사용할 수 있다면 어할 나위 없이 좋고...ㅎㅎㅎㅎ
앞으로 뭔가 험난한 길이 예상된다 ㅋㅋㅋㅋㅋㅋㅋㅋㅋ
'프로그래밍 > RUST' 카테고리의 다른 글
러스트 14 - 구조체 #2 : 메소드 (0) | 2019.03.10 |
---|---|
러스트 13 - 구조체 #1 (0) | 2019.03.10 |
러스트 11 - References와 Borrowing (0) | 2019.03.02 |
러스트 10 - Ownership : 소유권 #2 (0) | 2019.03.02 |
러스트 9 - Ownership : 소유권 #1 (0) | 2019.02.24 |