Language/Go

[Golang] Go 언어 문자열 선언 및 접근

Young-Cow 2021. 11. 18. 21:54

Go 언어 문자열

문자열의 선언

여기에서 string 타입의 변수를 어떻게 선언하는지 확인할 수 있다.

문자열의 변환

문자열은 1바이트의 아스키 문자열 또는 4바이트의 유니코드 문자열로 변환할 수 있다.

  • 문자열 -> 아스키 : []byte(string)
  • 문자열 -> 유니코드 : []rune(string)

또, 아스키코드 배열 또는 유니코드 배열을 문자열로 변환할 수 있다.

  • 아스키코드 배열 또는 유니코드 배열 -> 문자열 : string(chars)
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 인코딩의 유니코드 문자들이다. 유니코드는 문자에 따라 바이트 수가 다르기 때문에 문자열에 접근할 때 주의해야할 부분들이 있다.

인덱스로 접근할 때 주의사항

문자열 내부에 바이트 단위로 접근할 때는 인덱스([])를 사용한다.

유니코드는 문자에 따라 바이트 수가 다르기 때문에 별 생각없이 글자 수에 따라 인덱스에 접근하려 하면 원하지 않은 결과가 발생할 수 있다.

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 타입으로 변환하여 코드별로 묶어주면 안전하게 접근할 수 있다.

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 문을 사용하면 쉽다.

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() 함수를 사용하면 문자열의 바이트 수를 구할 수 있다.

문자열은 유니코드의 집합이기 때문에, 문자에 따라 바이트수가 다르다.

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() 함수를 사용하면 된다.

package main

import (
    "fmt"
    "unicode/utf8"
)

func main() {

    s2 := "안녕하세요"

    fmt.Println(len([]rune(s2)))
    fmt.Println(utf8.RuneCountInString(s2))
}
/*
출력 결과
5
5
*/

문자열을 수정할 때 주의사항

문자열은 한 번 생성되면 수정이 불가능한 Immutable 타입이다.

문자열을 변수에 대입한 뒤 다른 문자열을 다시 대입할 수는 있지만 문자열을 수정하려고 하면 에러가 발생한다.

728x90
반응형