기본 및 복합 데이터 타입
Go는 정형화된 타입 시스템을 기반으로 하며, 변수 선언 시 타입이 명확하게 지정되어야 합니다. 기본적으로 다음과 같은 데이터 타입들을 제공합니다.
기본 타입
- bool: 불리언 값 (true/false)
- 정수형: int8, int16, int32, int64, uint8(byte), uint32, uint64 등
- 실수형: float32, float64
- 복소수형: complex64, complex128
- 문자열: string
- 유니코드 문자: rune (int32别명)
- 에러 타입: error
복합 타입
- 포인터 (
*T) - 배열 (
[n]T) - 슬라이스 (
[]T) - 맵 (
map[K]V) - 채널 (
chan T) - 구조체 (
struct) - 인터페이스 (
interface{})
변수 선언과 초기화
Go에서는 var 키워드를 사용하여 변수를 선언하며, 타입은 변수 이름 뒤에 위치합니다. 예:
var count int
var name string = "golang"
여러 변수를 그룹으로 선언할 수도 있습니다:
var (
age int = 25
city string
isActive bool
)
타입 추론을 이용하면 var와 타입을 생략하고 짧은 선언(:=)을 사용할 수 있습니다:
message := "Hello, World"
number := 42
모든 변수는 암시적으로 해당 타입의 제로 값으로 초기화됩니다. 예를 들어, int는 0, bool은 false, string은 ""가 됩니다.
다중 할당과 익명 변수
Go는 다중 할당을 지원하므로 값을 쉽게 교환할 수 있습니다:
a, b := 10, 20
a, b = b, a // 값 교환
함수에서 반환값 중 일부만 사용하고 싶을 때는 익명 변수 _를 활용합니다:
func getUser() (string, string) {
return "alice", "developer"
}
_, role := getUser() // 이름은 무시하고 역할만 저장
상수와 iota
상수는 const 키워드로 정의되며, 컴파일 시 결정됩니다:
const Pi = 3.14159
const (
StatusOK = 200
StatusNotFound = 404
)
iota는 상수 생성기에 사용되며, const 블록 내에서 자동으로 증가하는 값을 제공합니다:
const (
Sunday = iota
Monday
Tuesday
Wednesday
Thursday
Friday
Saturday
)
위 코드에서 각 요일은 0부터 6까지 순차적으로 값을 가지게 됩니다. 이를 통해 열거형(enum)과 유사한 구조를 만들 수 있습니다.
정수형과 연산
Go는 다양한 크기의 정수형을 제공하며, 부호 있는 형(int)과 없는 형(uint)이 구분됩니다. 대표적인 형식은 다음과 같습니다:
| 타입 | 크기 | 범위 |
|---|---|---|
| int32 | 4바이트 | -2,147,483,648 ~ 2,147,483,647 |
| uint64 | 8바이트 | 0 ~ 18,446,744,073,709,551,615 |
서로 다른 정수형 간의 산술 연산은 명시적 캐스팅이 필요합니다:
var a int32 = 100
var b int64 = 200
var c int64 = b + int64(a) // OK
증감 연산자는 문장 단위에서만 사용 가능하며, 전위형(--i)은 허용되지 않습니다:
i := 5
i++ // 유효함
부동소수점과 비교
float32과 float64는 IEEE-754 표준을 따르며, 실수 계산에 사용됩니다. 하지만 정밀도 문제로 인해 직접적인 동등 비교는 위험합니다:
val1 := 0.1
val2 := 0.2
sum := val1 + val2
// sum == 0.3 ? 아님 (실제로는 근사치)
대신 작은 epsilon 값을 기준으로 범위 비교를 수행합니다:
import "math"
epsilon := 1e-9
if math.Abs(sum - 0.3) < epsilon {
// 거의 같다고 판단
}
문자열 처리
문자열은 UTF-8 인코딩을 기반으로 하며, 백틱(`)을 사용해 여러 줄로 정의할 수 있습니다:
text := `첫 번째 줄
두 번째 줄
세 번째 줄`
문자열 조합은 + 또는 fmt.Sprintf로 가능합니다:
greeting := "안녕하세요"
name := "지훈"
result := greeting + ", " + name
문자열 슬라이싱은 바이트 기반으로 동작하므로, 멀티바이트 문자에는 주의가 필요합니다:
s := "안녕, 세계"
fmt.Println(s[:3]) // 예측하기 어려운 결과 (UTF-8 바이트 기준)
유니코드 문자 단위로 반복하려면 range를 사용해야 합니다:
for i, r := range s {
fmt.Printf("위치 %d: %c\n", i, r)
}
타입 변환
Go는 엄격한 타입 시스템을 가지므로, 타입 간 변환은 명시적으로 이루어져야 합니다. 숫자형 간 변환은 타입 캐스팅으로 가능합니다:
num := 42
f := float64(num)
u := uint8(f)
문자열과 기본 타입 간 변환은 strconv 패키지를 사용합니다:
import "strconv"
s := "123"
i, _ := strconv.Atoi(s) // 문자열 → 정수
f, _ := strconv.ParseFloat(s, 64) // 문자열 → 실수
num := 456
str := strconv.Itoa(num) // 정수 → 문자열
또한, 바이트 배열이나 룬 배열을 문자열로 변환할 수도 있습니다:
bytes := []byte{'h', 'e', 'l', 'l', 'o'}
text := string(bytes)
runes := []rune{0xD55C, 0xAD6D} // 한글 "한국"
word := string(runes)