1. Go 언어 데이터 타입 소개
Go 언어에서 데이터 타입은 프로그래밍의 기초로, 변수가 저장할 수 있는 데이터의 형식을 결정합니다. Go 언어에서 제공하는 기본 데이터 타입은 주로 다음과 같은 범주로 나뉘어집니다:
데이터 타입 | 설명 | 메모리 사용량 |
---|---|---|
bool | 참 또는 거짓을 저장하는 부울(boolean) 타입 | 1바이트 |
int, uint | 부호 있는 정수와 부호 없는 정수, 기본 크기는 시스템 플랫폼에 따라 다름 | 4 또는 8바이트 |
int8, uint8 | 8비트 부호 있는 정수와 부호 없는 정수 | 1바이트 |
int16, uint16 | 16비트 부호 있는 정수와 부호 없는 정수 | 2바이트 |
int32, uint32 | 32비트 부호 있는 정수와 부호 없는 정수 | 4바이트 |
int64, uint64 | 64비트 부호 있는 정수와 부호 없는 정수 | 8바이트 |
float32 | 32비트 부동 소수점 숫자 | 4바이트 |
float64 | 64비트 부동 소수점 숫자 | 8바이트 |
complex64 | 32비트 실수부와 허수부를 가지는 복소수 | 8바이트 |
complex128 | 64비트 실수부와 허수부를 가지는 복소수 | 16바이트 |
byte | uint8과 유사 | 1바이트 |
rune | int32와 유사하며, 유니코드 코드 포인트를 나타냄 | 4바이트 |
string | 문자열 타입 | 문자열 길이에 따라 다름 |
error | 오류 정보를 반환하는 데 사용되는 오류 인터페이스 | 고정된 크기 없음 |
이러한 데이터 타입은 숫자 계산, 텍스트 처리 또는 논리적 제어 등 다양한 요구에 따라 선택할 수 있습니다.
2. 정수형 데이터 타입
2.1 정수형 타입 개요
Go 언어에는 여러 내장 정수형 타입이 있으며, 다음과 같이 분류됩니다:
- 부호 있는 정수:
int8
,int16
,int32
(또는rune
),int64
,int
- 부호 없는 정수:
uint8
(또는byte
),uint16
,uint32
,uint64
,uint
int
와 uint
의 크기는 32비트 시스템에서는 4바이트이고, 64비트 시스템에서는 8바이트입니다. 정수 데이터 타입의 값 범위는 아래 표에 나와 있습니다:
타입 | 값 범위 |
---|---|
int8 | -128부터 127까지 |
uint8 | 0부터 255까지 |
int16 | -32768부터 32767까지 |
uint16 | 0부터 65535까지 |
int32 | -2147483648부터 2147483647까지 |
uint32 | 0부터 4294967295까지 |
int64 | -9223372036854775808부터 9223372036854775807까지 |
uint64 | 0부터 18446744073709551615까지 |
2.2 정수 변수 사용하기
정수 변수를 선언하는 기본 구문은 아래와 같습니다:
var 변수_이름 데이터_타입 = 초기_값
예시 코드:
package main
import "fmt"
func main() {
var a int = 10 // 부호 있는 정수 변수
var b uint = 20 // 부호 없는 정수 변수
var c int8 = -128 // 가장 작은 int8 값
fmt.Println(a, b, c)
}
2.3 정수 연산
Go 언어는 덧셈 (+
), 뺄셈 (-
), 곱셈 (*
), 나눗셈 (/
), 나머지 (%
) 등의 일반 산술 연산자를 지원하며, 비트 연산자인 비트 AND (&
), OR (|
), XOR (^
), 좌측 시프트 (<<
), 우측 시프트 (>>
)도 지원합니다.
package main
import "fmt"
func main() {
x := 10
y := 3
// 산술 연산
fmt.Println(x + y) // 덧셈
fmt.Println(x - y) // 뺄셈
fmt.Println(x * y) // 곱셈
fmt.Println(x / y) // 나눗셈
fmt.Println(x % y) // 나머지
// 비트 연산
fmt.Println(x & y) // 비트 AND
fmt.Println(x | y) // 비트 OR
fmt.Println(x ^ y) // 비트 XOR
fmt.Println(x << 1) // 좌측 시프트 1회
fmt.Println(x >> 1) // 우측 시프트 1회
}
3. 부동 소수점 데이터 타입
3.1 부동 소수점 데이터 유형 개요
Go 언어에서는 부동 소수점 유형으로 float32
와 float64
가 있으며, 각각 32비트와 64비트 부동 소수점 데이터에 해당합니다. 일반적으로 더 큰 범위와 더 정확한 정밀도를 제공하는 float64
를 사용하는 것이 권장됩니다.
-
float32
는 약 23개의 유효 비트를 가지며, 약 7자리의 십진수 정밀도를 제공합니다. -
float64
는 약 52개의 유효 비트를 가지며, 약 16자리의 십진수 정밀도를 제공합니다.
3.2 부동 소수점 변수 사용하기
부동 소수점 변수는 리터럴을 직접 제공하거나 var
키워드를 사용하여 선언할 수 있습니다.
package main
import "fmt"
func main() {
var f1 float32 = 3.14 // 명시적으로 float32 유형 지정
f2 := 3.14 // float64 유형으로 자동 추론
fmt.Println(f1, f2)
}
3.3 부동 소수점 산술 및 이슈
부동 소수점 산술은 정밀도 손실을 유발할 수 있습니다. 특히 두 매우 가까운 숫자를 빼는 경우와 같이 매우 높은 정밀도로 작업하는 것은 일반적인 문제입니다.
package main
import "fmt"
func main() {
f1 := .1
f2 := .2
f3 := f1 + f2
fmt.Println(f3) // 정밀도 문제로 예상한 .3이 출력되지 않을 수 있음
// 형식화된 출력을 사용하여 정밀도 문제 해결
fmt.Printf("%.1f\n", f3) // 출력이 .3으로 수정됨
}
4 부울 데이터 유형
4.1 부울 데이터 유형 개요
부울은 가장 간단한 데이터 유형으로, true
(참)와 false
(거짓) 두 가지 값만 가질 수 있습니다. 조건문과 루프 제어 구조에서 매우 중요한 역할을 합니다.
4.2 부울 변수 사용하기
부울 변수를 선언하고 사용하는 방법:
package main
import "fmt"
func main() {
var success bool = true
var fail bool = false
fmt.Println("작업 성공:", success)
fmt.Println("작업 실패:", fail)
}
부울 값은 종종 조건문에서 사용됩니다:
package main
import "fmt"
func main() {
a := 10
b := 20
fmt.Println("a == b:", a == b) // false
fmt.Println("a < b:", a < b) // true
}
5 문자열 데이터 유형
5.1 문자열 개요
문자열은 문자의 모음입니다. Go 언어에서 문자열은 변경할 수 없습니다. 각 문자열은 기본 바이트 배열의 포인터와 길이로 구성됩니다. 문자열은 바이트를 포함한 모든 데이터를 담을 수 있습니다.
5.2 문자열 변수 사용하기
문자열 변수는 일반적으로 이중 인용부호 "
를 사용하여 만들지만, 여러 줄의 문자열을 만들기 위해 백틱 `을 사용할 수도 있습니다:
package main
import "fmt"
func main() {
var s1 string = "hello"
s2 := "world"
s3 := `여러 줄로
구성된
문자열`
fmt.Println(s1)
fmt.Println(s2)
fmt.Println(s3)
}
문자열이 생성되면 그 내용을 변경할 수 없습니다. 다음 작업은 부적절하며 컴파일 오류를 유발합니다:
s := "hello"
s[] = 'H` // 컴파일 오류: 문자열 내용은 변경할 수 없음
5.3 문자열 작업
문자열은 프로그래밍에서 매우 일반적이고 중요합니다. Go 언어는 문자열 조작을 위한 다양한 내장 함수를 제공합니다. 일반적으로 사용되는 몇 가지 작업은 다음과 같습니다.
5.3.1 문자열 연결
Go 언어에서 문자열을 연결하기 위해 더하기 기호 (+
) 연산자를 사용할 수 있으며, 성능을 위해 여러 문자열을 빈번하게 연결해야 하는 경우에는 strings.Builder
를 사용하는 것이 좋습니다.
package main
import (
"fmt"
"strings"
)
func main() {
// +를 사용하여 문자열 연결
hello := "안녕, "
world := "세상!"
result := hello + world
fmt.Println(result) // 출력: 안녕, 세상!
// strings.Builder를 사용하여 문자열 연결
var sb strings.Builder
sb.WriteString("안녕, ")
sb.WriteString("세상!")
fmt.Println(sb.String()) // 출력: 안녕, 세상!
}
5.3.2 문자열 분할
문자열을 지정된 구분자를 기반으로 슬라이스로 분할하는 작업은 strings.Split
함수를 사용하여 수행할 수 있습니다.
package main
import (
"fmt"
"strings"
)
func main() {
// 문자열 정의
sentence := "Go는 오픈 소스 프로그래밍 언어입니다"
// 공백을 기준으로 문자열 분할
words := strings.Split(sentence, " ")
for _, word := range words {
fmt.Printf("%s\n", word)
}
// 결과:
// Go는
// 오픈
// 소스
// 프로그래밍
// 언어입니다
}
5.3.3 인덱스 접근
Go 언어에서 문자열은 변경할 수 없는 바이트 시퀀스입니다. 특정 바이트에 접근하기 위해 인덱싱을 사용할 수 있습니다. 그러나 UTF-8로 인코딩된 문자와 같은 다중바이트 문자가 포함된 문자열의 경우, 직접적인 인덱싱은 예상한 단일 문자를 얻을 수 없음에 유의해야 합니다.
package main
import "fmt"
func main() {
s := "Hello, 世界"
for i := 0; i < len(s); i++ {
fmt.Printf("%d: %x\n", i, s[i])
}
// 참고: 이는 문자가 아닌 바이트의 16진수 표현을 출력합니다
}
문자 단위로 문자열을 반복하려면 range
루프를 사용할 수 있습니다.
package main
import "fmt"
func main() {
s := "Hello, 世界"
for index, runeValue := range s {
fmt.Printf("%d: %U '%c'\n", index, runeValue, runeValue)
}
// 출력: 각 문자에 대한 인덱스, 유니코드 인코딩, 그리고 해당 문자
}
5.3.4 길이 가져오기
len
함수는 문자열의 길이, 즉 기본 바이트 시퀀스의 길이를 얻을 수 있습니다. UTF-8 문자열의 경우, 문자(룬)의 수를 얻으려면 utf8.RuneCountInString
함수를 사용해야 합니다. 이 함수는 다중바이트 문자를 올바르게 처리할 수 있습니다.
package main
import (
"fmt"
"unicode/utf8"
)
func main() {
s := "Hello, 世界"
fmt.Println("바이트 길이:", len(s)) // 바이트 길이 출력
fmt.Println("문자 길이:", utf8.RuneCountInString(s)) // 문자 길이 출력
}
위의 예에서 보듯이 Go 언어는 다양한 문자열 처리 작업을 쉽게 수행할 수 있도록 풍부한 라이브러리 함수를 제공합니다. 코딩할 때, 특히 비 ASCII 문자 세트를 다룰 때에는 바이트와 문자 사이의 구별에 주의해야 합니다.