『Tucker의 Go 언어 프로그래밍』 스터디 요약 노트입니다.
15장. 문자열
문자열의 Go 언어에서의 특징만 확인해보자.
- backquote(`)으로 문자열을 감싸면 줄바꿈을 포함한 모든 문자열을 원형으로 작성할 수 있다.
- 기본적으로 UTF-8로 문자열이 인코딩된다.
range
로 각 문자를rune
단위로 순회할 수 있다.- 연산자(+=, ==, !=, <=)를 통해 문자열을 합치거나, 비교할 수 있다.
- 문자열의 내용은 불변이다.
여기서 UTF-8 인코딩에 관한 확인은 ch04에서 이미 실험한 바 있으므로 변환 과정은 생략하도록 하겠다.
문자열 순회하기
문자열을 순회하는 방법에는 세가지 방법이 존재한다.
- 문자열을 바로 배열 취급하여
byte
단위로 순회 - 문자열을
[]rune
으로 타입 변환하여 배열 순회 range
로rune
단위로 순회
|
|
|
|
|
|
$ ./go_string_traversal_index
backquote로 감싸진 string은
그대로 줄바꿈이 되지만 \n은 동작하지 않습니다.
Type: uint8 Value: 98 Char: b
Type: uint8 Value: 97 Char: a
Type: uint8 Value: 99 Char: c
Type: uint8 Value: 107 Char: k
Type: uint8 Value: 113 Char: q
Type: uint8 Value: 117 Char: u
Type: uint8 Value: 111 Char: o
Type: uint8 Value: 116 Char: t
Type: uint8 Value: 101 Char: e
Type: uint8 Value: 235 Char: ë
Type: uint8 Value: 161 Char: ¡
Type: uint8 Value: 156 Char:
Type: uint8 Value: 32 Char:
Type: uint8 Value: 234 Char: ê
Type: uint8 Value: 176 Char: °
Type: uint8 Value: 144 Char:
Type: uint8 Value: 236 Char: ì
Type: uint8 Value: 139 Char:
Type: uint8 Value: 184 Char: ¸
Type: uint8 Value: 236 Char: ì
Type: uint8 Value: 167 Char: §
Type: uint8 Value: 132 Char:
Type: uint8 Value: 32 Char:
Type: uint8 Value: 115 Char: s
Type: uint8 Value: 116 Char: t
Type: uint8 Value: 114 Char: r
Type: uint8 Value: 105 Char: i
Type: uint8 Value: 110 Char: n
Type: uint8 Value: 103 Char: g
Type: uint8 Value: 236 Char: ì
Type: uint8 Value: 157 Char:
Type: uint8 Value: 128 Char:
Type: uint8 Value: 10 Char:
Type: uint8 Value: 234 Char: ê
Type: uint8 Value: 183 Char: ·
Type: uint8 Value: 184 Char: ¸
Type: uint8 Value: 235 Char: ë
Type: uint8 Value: 140 Char:
Type: uint8 Value: 128 Char:
Type: uint8 Value: 235 Char: ë
Type: uint8 Value: 161 Char: ¡
Type: uint8 Value: 156 Char:
Type: uint8 Value: 32 Char:
Type: uint8 Value: 236 Char: ì
Type: uint8 Value: 164 Char: ¤
Type: uint8 Value: 132 Char:
Type: uint8 Value: 235 Char: ë
Type: uint8 Value: 176 Char: °
Type: uint8 Value: 148 Char:
Type: uint8 Value: 234 Char: ê
Type: uint8 Value: 191 Char: ¿
Type: uint8 Value: 136 Char:
Type: uint8 Value: 236 Char: ì
Type: uint8 Value: 157 Char:
Type: uint8 Value: 180 Char: ´
Type: uint8 Value: 32 Char:
Type: uint8 Value: 235 Char: ë
Type: uint8 Value: 144 Char:
Type: uint8 Value: 152 Char:
Type: uint8 Value: 236 Char: ì
Type: uint8 Value: 167 Char: §
Type: uint8 Value: 128 Char:
Type: uint8 Value: 235 Char: ë
Type: uint8 Value: 167 Char: §
Type: uint8 Value: 140 Char:
Type: uint8 Value: 32 Char:
Type: uint8 Value: 92 Char: \
Type: uint8 Value: 110 Char: n
Type: uint8 Value: 236 Char: ì
Type: uint8 Value: 157 Char:
Type: uint8 Value: 128 Char:
Type: uint8 Value: 32 Char:
Type: uint8 Value: 235 Char: ë
Type: uint8 Value: 143 Char:
Type: uint8 Value: 153 Char:
Type: uint8 Value: 236 Char: ì
Type: uint8 Value: 158 Char:
Type: uint8 Value: 145 Char:
Type: uint8 Value: 237 Char: í
Type: uint8 Value: 149 Char:
Type: uint8 Value: 152 Char:
Type: uint8 Value: 236 Char: ì
Type: uint8 Value: 167 Char: §
Type: uint8 Value: 128 Char:
Type: uint8 Value: 32 Char:
Type: uint8 Value: 236 Char: ì
Type: uint8 Value: 149 Char:
Type: uint8 Value: 138 Char:
Type: uint8 Value: 236 Char: ì
Type: uint8 Value: 138 Char:
Type: uint8 Value: 181 Char: µ
Type: uint8 Value: 235 Char: ë
Type: uint8 Value: 139 Char:
Type: uint8 Value: 136 Char:
Type: uint8 Value: 235 Char: ë
Type: uint8 Value: 139 Char:
Type: uint8 Value: 164 Char: ¤
Type: uint8 Value: 46 Char: .
$ ./go_string_traversal_rune_array
[98 97 99 107 113 117 111 116 101 47196 32 44048 49912 51652 32 115 116 114 105 110 103 51008 10 44536 45824 47196 32 51460 48148 45000 51060 32 46104 51648 47564 32 92 110 51008 32 46041 51089 54616 51648 32 50506 49845 45768 45796 46]
Type: int32 Value: 98 Char: b
Type: int32 Value: 97 Char: a
Type: int32 Value: 99 Char: c
Type: int32 Value: 107 Char: k
Type: int32 Value: 113 Char: q
Type: int32 Value: 117 Char: u
Type: int32 Value: 111 Char: o
Type: int32 Value: 116 Char: t
Type: int32 Value: 101 Char: e
Type: int32 Value: 47196 Char: 로
Type: int32 Value: 32 Char:
Type: int32 Value: 44048 Char: 감
Type: int32 Value: 49912 Char: 싸
Type: int32 Value: 51652 Char: 진
Type: int32 Value: 32 Char:
Type: int32 Value: 115 Char: s
Type: int32 Value: 116 Char: t
Type: int32 Value: 114 Char: r
Type: int32 Value: 105 Char: i
Type: int32 Value: 110 Char: n
Type: int32 Value: 103 Char: g
Type: int32 Value: 51008 Char: 은
Type: int32 Value: 10 Char:
Type: int32 Value: 44536 Char: 그
Type: int32 Value: 45824 Char: 대
Type: int32 Value: 47196 Char: 로
Type: int32 Value: 32 Char:
Type: int32 Value: 51460 Char: 줄
Type: int32 Value: 48148 Char: 바
Type: int32 Value: 45000 Char: 꿈
Type: int32 Value: 51060 Char: 이
Type: int32 Value: 32 Char:
Type: int32 Value: 46104 Char: 되
Type: int32 Value: 51648 Char: 지
Type: int32 Value: 47564 Char: 만
Type: int32 Value: 32 Char:
Type: int32 Value: 92 Char: \
Type: int32 Value: 110 Char: n
Type: int32 Value: 51008 Char: 은
Type: int32 Value: 32 Char:
Type: int32 Value: 46041 Char: 동
Type: int32 Value: 51089 Char: 작
Type: int32 Value: 54616 Char: 하
Type: int32 Value: 51648 Char: 지
Type: int32 Value: 32 Char:
Type: int32 Value: 50506 Char: 않
Type: int32 Value: 49845 Char: 습
Type: int32 Value: 45768 Char: 니
Type: int32 Value: 45796 Char: 다
Type: int32 Value: 46 Char: .
$ ./go_string_traversal_range
backquote로 감싸진 string은
그대로 줄바꿈이 되지만 \n은 동작하지 않습니다.
Type: int32 Value: 98 Char: b
Type: int32 Value: 97 Char: a
Type: int32 Value: 99 Char: c
Type: int32 Value: 107 Char: k
Type: int32 Value: 113 Char: q
Type: int32 Value: 117 Char: u
Type: int32 Value: 111 Char: o
Type: int32 Value: 116 Char: t
Type: int32 Value: 101 Char: e
Type: int32 Value: 47196 Char: 로
Type: int32 Value: 32 Char:
Type: int32 Value: 44048 Char: 감
Type: int32 Value: 49912 Char: 싸
Type: int32 Value: 51652 Char: 진
Type: int32 Value: 32 Char:
Type: int32 Value: 115 Char: s
Type: int32 Value: 116 Char: t
Type: int32 Value: 114 Char: r
Type: int32 Value: 105 Char: i
Type: int32 Value: 110 Char: n
Type: int32 Value: 103 Char: g
Type: int32 Value: 51008 Char: 은
Type: int32 Value: 10 Char:
Type: int32 Value: 44536 Char: 그
Type: int32 Value: 45824 Char: 대
Type: int32 Value: 47196 Char: 로
Type: int32 Value: 32 Char:
Type: int32 Value: 51460 Char: 줄
Type: int32 Value: 48148 Char: 바
Type: int32 Value: 45000 Char: 꿈
Type: int32 Value: 51060 Char: 이
Type: int32 Value: 32 Char:
Type: int32 Value: 46104 Char: 되
Type: int32 Value: 51648 Char: 지
Type: int32 Value: 47564 Char: 만
Type: int32 Value: 32 Char:
Type: int32 Value: 92 Char: \
Type: int32 Value: 110 Char: n
Type: int32 Value: 51008 Char: 은
Type: int32 Value: 32 Char:
Type: int32 Value: 46041 Char: 동
Type: int32 Value: 51089 Char: 작
Type: int32 Value: 54616 Char: 하
Type: int32 Value: 51648 Char: 지
Type: int32 Value: 32 Char:
Type: int32 Value: 50506 Char: 않
Type: int32 Value: 49845 Char: 습
Type: int32 Value: 45768 Char: 니
Type: int32 Value: 45796 Char: 다
Type: int32 Value: 46 Char: .
문자열 연산자
+
, +=
연산자를 사용하여 문자열을 합칠 수 있다. ==
!=
연산자로 두 문자열이 같은지, 다른지 확인할 수 있으며, >=
, <=
연산자로 두 문자열을 유니코드 값 기준으로 순서를 비교할 수 있다.
|
|
$ ./go_string_operators
helloworld
hello world!
It is false that "helloworld" is equal with "hello world!"
helloworld comes after hello world! when strings are sorted in Unicode order
문자열의 구현 방식, 불변성
string
의 내부 구현은 실제 문자열 데이터(UTF-8로 인코딩된 []byte
, 해당 배열을 가리키는 포인터)와 해당 배열의 길이를 나타내는 길이로 표현하고 있다.
그리고 StringHeader
구조체를 통해 해당 string
의 내부를 엿볼수 있다.
문자열을 복사할 때는 메모리 관리를 효율적으로 하기 위해 해당 배열을 가리키는 포인터와 배열의 길이만 복사한다.
그리고 문자열의 데이터는 불변이기 때문에 임의로 코드에서 변경할 수 없다.
임의로 문자열의 데이터를 변경하려면 []byte
와 같이 자료형을 변환하고 해당 slice
에서 수정해야 한다.
|
|
$ ./go_string_internals
&{4343664238 11}
Healo world
&{1374389641488 11 16}
Healo world
&{1374389641520 11}
실행 결과를 보고 예측할 수 있는 점은 아래와 같다.
- 초기 사용된
str
의 값은 상수 값으로 하드코딩된 값으로 들어간다. - 문자열을
slice
로 동적 변환했으므로, 해당 변수는 힙에 할당된다. - 변경된
slice
에서 다시 문자열로 변환하면 불변성을 유지해야 하기 때문에 새로운 주소에 해당 내용을 복사한다.