Go 프로그래밍 - 문자열

beno·2021년 6월 28일
0

golang

목록 보기
4/8

UTF-8 문자코드

golang에서는 기본적으로 UTF-8 인코딩을 사용한다.

  • 1~3 바이트 가변문자
  • ANSI 코드와 1:1 대응이 되어 바로 변환

문자열

문자열이란 문자의 집합을 의미
타입: string

package main

import "fmt"

func main() {
	// 1. 큰따옴표 사용
	// 큰따옴표로 묶으면 특수문자 동작 (개행, 탭 등)
	str1 := "Hello\t'world'\n"

	// 2. 백쿼트 사용
	// 백쿼트로 묶으면 특수문자가 동작하지 않음
	str2 := `Go is "awesome"!\nGo is simple and\t 'powerful'`
	// 여러줄에 걸쳐서 작성 가능
	str3 :=
		`Hello
My name is kang
Thank you :)
`

rune 타입으로 한 문자 담기

rune = int32 타입의 별칭 타입

  • 기본적으로 utf-8은 3바이트
  • 하지만 golang에는 3바이트 정수 타입이 없기 때문에 int32를 사용한다.
package main

import "fmt"

func main() {
	var char rune = '한'

	fmt.Printf("%T\n", char) 	// char 타입 출력
	// > int32

	fmt.Println(char)        	// char 값 출력.
	// > 54620

	fmt.Printf("%c\n", char)	// 문자 출력.
	// > 한

}

len()으로 문자열 크기 알아내기

문자 수가 아닌, 문자열이 차지하는 메모리 크기를 의미

package main

import "fmt"

func main() {
	str1 := "가나다라마"
	str2 := "abcde"

	fmt.Println(len(str1))
	// > 15
	
	fmt.Println(len(str2))
	// > 5
}
  • 한글은 글자 당 3 바이트를 차지 => str1은 15바이트
  • 영문은 글자당 1바이트를 차지 => str2는 5바이트

[]rune 타입 변환으로 글자 수 알아내기

[]rune <-> string 은 상호변환이 가능하다.

  • string([]rune) 또는 []rune(string)의 형태로 상호 타입 변환 가능.
package main

import "fmt"

func main() {
	str := "abcde"
	runes := []rune{97, 98, 99, 100, 101}
	runes_to_str := string(runes)
	str_to_runes := []rune(str)

	fmt.Println(runes_to_str)
	// > abcde

	fmt.Println(str_to_runes)
	// > [97 98 99 100 101]
}

package main

import "fmt"

func main() {
	str1 := "가나다라마"
	str1_to_runes := []rune(str1)
	fmt.Println(len(str1))
	// > 15 (바이트수)
	fmt.Println(len(str1_to_runes))
	// > 5	(글자수)
}

문자열 순회하는 방법

1. 인덱스로 순회

  • 바이트 단위로 순회한다.
  • 1바이트가 넘어가는 경우 글자가 깨짐
package main

import "fmt"

func main() {
	str1 := "hello 월드!"
	// str1_to_runes := []rune(str1)
	
	// 1. 인덱스로 순회.
	for i := 0; i < len(str1); i++ {
		fmt.Printf("타입: %T, 값: %d, 문자: %c\n", str1[i], str1[i], str1[i])
	}
	// 타입: uint8, 값: 104, 문자: h
	// 타입: uint8, 값: 101, 문자: e
	// 타입: uint8, 값: 108, 문자: l
	// 타입: uint8, 값: 108, 문자: l
	// 타입: uint8, 값: 111, 문자: o
	// 타입: uint8, 값: 32, 문자:  
	// 타입: uint8, 값: 236, 문자: ì
	// 타입: uint8, 값: 155, 문자: ›
	// 타입: uint8, 값: 148, 문자: ”
	// 타입: uint8, 값: 235, 문자: ë
	// 타입: uint8, 값: 147, 문자: “
	// 타입: uint8, 값: 156, 문자: œ
	// 타입: uint8, 값: 33, 문자: !

}

2. []rune으로 변환 후 순회

  • 바이트 단위가 아닌 문자 단위로 한글자씩 순회
package main

import "fmt"

func main() {
	str1 := "hello 월드!"

	// 2. rune 타입 변환 후 한글자씩 순회하기
	str1_to_runes := []rune(str1)

	// 1. 인덱스로 순회.
	for i := 0; i < len(str1_to_runes); i++ {
		fmt.Printf("타입: %T, 값: %d, 문자: %c\n", str1_to_runes[i], str1_to_runes[i], str1_to_runes[i])
	}
	// 타입: int32, 값: 104, 문자: h
	// 타입: int32, 값: 101, 문자: e
	// 타입: int32, 값: 108, 문자: l
	// 타입: int32, 값: 108, 문자: l
	// 타입: int32, 값: 111, 문자: o
	// 타입: int32, 값: 32, 문자:  
	// 타입: int32, 값: 50900, 문자: 월
	// 타입: int32, 값: 46300, 문자: 드
	// 타입: int32, 값: 33, 문자: !

}

3. range 키워드를 이용해 한글자씩 순회

  • 가장 간단한 방법
  • 코드가 간결하고 추가 메모리할당이 필요 없는 방법
package main

import "fmt"

func main() {
	str1 := "hello 월드!"

	for _, v := range str1 {
		fmt.Printf("타입: %T, 값: %d, 문자: %c\n", v, v, v)
	}
	// 타입: int32, 값: 104, 문자: h
	// 타입: int32, 값: 101, 문자: e
	// 타입: int32, 값: 108, 문자: l
	// 타입: int32, 값: 108, 문자: l
	// 타입: int32, 값: 111, 문자: o
	// 타입: int32, 값: 32, 문자:
	// 타입: int32, 값: 50900, 문자: 월
	// 타입: int32, 값: 46300, 문자: 드
	// 타입: int32, 값: 33, 문자: !
}

문자열은 불변이다

불변 = 일부만 변경할 수 없다.

package main

import "fmt"

func main() {
	var str string = "hello world"

	// 슬라이스로 복사. 단 주소값이 다름.
	var slice []byte = []byte(str)

	bytes[2] = 'a'

	fmt.Println(str)
	// > hello world
	fmt.Printf("%s\n", bytes)
 	// > healo world
}

위의 경우 strslice의 주소값이 다르다. []byte 객체가 할당될때 기존 str에서 바이트단위로 하나씩 값을 복사해오는 형태로 옮겨진다. 그렇다면 실제 주소값을 확인해보자.

package main

import (
	"fmt"
	"reflect"
	"unsafe"
)

func main() {
	var str string = "hello world"
	var slice []byte = []byte(str)

	stringheader := (*reflect.StringHeader)(unsafe.Pointer(&str))
	sliceheader := (*reflect.SliceHeader)(unsafe.Pointer(&slice))

	fmt.Printf("str:\t%x\n", stringheader.Data)
	fmt.Printf("slice:\t%x\n", sliceheader.Data)

}
profile
마음은 여기에. 시선은 저 멀리.

0개의 댓글

관련 채용 정보