Go 언어
문자열
문자열의 선언
여기에서 string 타입의 변수를 어떻게 선언하는지 확인할 수 있다.
문자열의 변환
문자열은 1바이트의 아스키 문자열 또는 4바이트의 유니코드 문자열로 변환할 수 있다.
- 문자열 -> 아스키 :
[]byte(string)
- 문자열 -> 유니코드 :
[]rune(string)
또, 아스키코드 배열 또는 유니코드 배열을 문자열로 변환할 수 있다.
- 아스키코드 배열 또는 유니코드 배열 -> 문자열 :
string(chars)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
var s1 string = "Hello"
fmt.Println([]rune(s1)) // 문자열->유니코드 로 변환
fmt.Println([]byte(s1)) // 문자열->아스키코드 로 변환
fmt.Println(string([]rune(s1))) // 문자열->유니코드->문자열 으로 변환
fmt.Println(string([]byte(s1))) // 문자열->아스키코드->문자열 으로 변환
var s2 string = "안녕하세요"
fmt.Println([]rune(s2)) // 문자열->유니코드 로 변환
fmt.Println([]byte(s2)) // 문자열->아스키코드 로 변환
fmt.Println(string([]rune(s2))) // 문자열->유니코드->문자열 으로 변환
fmt.Println(string([]byte(s2))) // 문자열->아스키코드->문자열 으로 변환
/*
출력 결과
[72 101 108 108 111]
[72 101 108 108 111]
Hello
Hello
[50504 45397 54616 49464 50836]
[236 149 136 235 133 149 237 149 152 236 132 184 236 154 148]
안녕하세요
안녕하세요
*/
문자열 접근 방법 및 주의사항
Go언어에서 문자열은 UTF-8 인코딩의 유니코드 문자들이다. 유니코드는 문자에 따라 바이트 수가 다르기 때문에 문자열에 접근할 때 주의해야할 부분들이 있다.
인덱스로 접근할 때 주의사항
문자열 내부에 바이트 단위로 접근할 때는 인덱스([]
)를 사용한다.
유니코드는 문자에 따라 바이트 수가 다르기 때문에 별 생각없이 글자 수에 따라 인덱스에 접근하려 하면 원하지 않은 결과가 발생할 수 있다.
1
2
3
4
5
6
7
8
9
s1 := "Hello"
s2 := "안녕하세요"
fmt.Printf("%c %c %c %c %c\n", s1[0], s1[1], s1[2], s1[3], s1[4])
fmt.Printf("%c %c %c %c %c", s2[0], s2[1], s2[2], s2[3], s2[4])
/*
출력 결과
H e l l o
ì ë
*/
이를 해결하려면 문자열을 []rune
타입으로 변환하여 코드별로 묶어주면 안전하게 접근할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
s1 := "Hello"
s2 := "안녕하세요"
r1 := []rune(s1)
r2 := []rune(s2)
fmt.Printf("%c %c %c %c %c\n", r1[0], r1[1], r1[2], r1[3], r1[4])
fmt.Printf("%c %c %c %c %c", r2[0], r2[1], r2[2], r2[3], r2[4])
/*
출력 결과
H e l l o
안 녕 하 세 요
*/
문자열의 각 문자에 순차적으로 접근하려면 for range
문을 사용하면 쉽다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
s1 := "Hello"
s2 := "안녕하세요"
for i, c := range s1 {
fmt.Printf("%c(%d) ", c, i)
}
fmt.Println()
for i, c := range s2 {
fmt.Printf("%c(%d) ", c, i)
}
/*
출력 결과
H(0) e(1) l(2) l(3) o(4)
안(0) 녕(3) 하(6) 세(9) 요(12)
*/
길이 구할 때 주의사항
len()
함수를 사용하면 문자열의 바이트 수를 구할 수 있다.
문자열은 유니코드의 집합이기 때문에, 문자에 따라 바이트수가 다르다.
1
2
3
4
5
6
7
8
9
10
s1 := "Hello"
s2 := "안녕하세요"
fmt.Println(len(s1))
fmt.Println(len(s2))
/*
출력 결과
5
15
*/
왜 “안녕하세요” 5 글자의 바이트수가 15일까?
“안녕하세요” 를 UTF-8로 변환하면
%EC%95%88(안) %EB%85%95(녕) %ED%95%98(하) %EC%84%B8(세) %EC%9A%94(요)
가 된다.
즉, 문자당 3 바이트의 코드를 갖고, 5문자 이므로 길이(바이트수)는 15가 되는 것이다.
문자열의 문자 수를 구하고 싶다면 []rune
타입으로 형변환 후 len()
함수로 길이를 구하거나
unicode/utf8
패키지의 utf8.RuneCountInString()
함수를 사용하면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
s2 := "안녕하세요"
fmt.Println(len([]rune(s2)))
fmt.Println(utf8.RuneCountInString(s2))
}
/*
출력 결과
5
5
*/
문자열을 수정할 때 주의사항
문자열은 한 번 생성되면 수정이 불가능한 Immutable 타입이다.
문자열을 변수에 대입한 뒤 다른 문자열을 다시 대입할 수는 있지만 문자열을 수정하려고 하면 에러가 발생한다.