Go 상수 기초

GolangBeginner
지금 연습하기

소개

이전 강의에서는 Go 의 변수에 대해 알아보았습니다. 이번 시간에는 상수의 개념과 사용 방법, 그리고 상수가 왜 중요한지에 대해 깊이 있게 살펴보겠습니다. 그럼 상수의 세계로 들어가 볼까요?

학습 포인트:

  • 상수의 정의
  • 상수 선언 방법
  • iota 상수 생성기 활용
  • 실전 상수 사용법

상수란 무엇인가?

간단히 말해, 상수는 한 번 선언되면 프로그램 실행 도중에 그 값을 절대 변경할 수 없는 데이터를 의미합니다. 상수를 사용하면 컴파일러가 프로그램이 실행되기 전인 컴파일 단계에서 이미 그 값을 파악할 수 있습니다.

상수 선언 시에는 특정 값을 할당해야 합니다. 문법은 변수와 매우 유사하지만, 일단 값이 정해지면 나중에 수정할 수 없다는 점이 가장 큰 차이점입니다.

상수는 웹사이트 주소나 원주율 (π) 과 같이 프로그램 전체에서 변하지 않아야 하는 고정된 값을 정의할 때 매우 유용합니다.

상수 선언하기

상수를 선언하는 방식은 변수와 비슷합니다. 다만 var 키워드 대신 const 키워드를 사용합니다.

주의: 상수는 선언과 동시에 반드시 값을 할당해야 합니다.

Go 언어에서는 정의된 모든 변수를 반드시 사용해야 하지만, 상수는 예외입니다. 상수는 선언만 하고 사용하지 않더라도 컴파일 오류가 발생하지 않습니다.

상수 선언 문법은 다음과 같습니다.

const name [type] = value

name은 상수의 이름입니다. type은 데이터 타입을 의미하며, Go 의 타입 추론 기능 덕분에 생략이 가능합니다. 마지막의 value는 상수에 할당할 실제 값입니다.

상수 선언에는 다음과 같은 타입들만 사용할 수 있다는 점에 유의하세요.

  • 정수 타입 (Integer)
  • 부동 소수점 타입 (Floating-point)
  • 복소수 타입 (Complex)
  • 불리언 타입 (Boolean)
  • 문자열 타입 (String)

이제 예제를 살펴보겠습니다. ~/project 디렉토리에 const.go라는 새 파일을 생성합니다.

touch ~/project/const.go

const.go 파일에 다음 코드를 작성하세요.

package main

import "fmt"

// 단일 상수 선언
const labex string = "LabEx" // 타입을 string 으로 명시적 지정
const labs = "LABS"    // 컴파일러가 자동으로 string 으로 추론

// 여러 상수 동시 선언
const (
    hangzhou, chengdu = "HANGZHOU", "CHENGDU"
    monday, tuesday, wednesday = "MONDAY", "TUESDAY", "WEDNESDAY"
)

func main() {
    fmt.Printf("The type of labex is: %T, and its value is %s\n", labex, labex)
    fmt.Printf("The type of labs is: %T, and its value is %s\n", labs, labs)

    fmt.Println()

    fmt.Println(hangzhou, chengdu)
    fmt.Println(monday, tuesday, wednesday)
}

작성한 코드를 실행합니다.

go run ~/project/const.go

실행 결과는 다음과 같습니다.

The type of labex is: string, and its value is LabEx
The type of labs is: string, and its value is LABS

HANGZHOU CHENGDU
MONDAY TUESDAY WEDNESDAY

위 예제에서는 단일 상수와 다중 상수를 선언하는 방법을 보여주었습니다. 여러 상수를 한꺼번에 선언할 때는 괄호를 사용하는 것이 관례이며 가독성 면에서도 권장됩니다.

여기서는 문자열 상수만 다루었지만, 정수나 불리언 등 다른 타입도 동일한 방식으로 선언할 수 있습니다.

괄호를 사용하여 여러 상수를 선언할 때, 만약 특정 상수에 값을 할당하지 않으면 바로 직전에 선언된 상수의 값을 그대로 물려받습니다.

const.go 파일을 다음과 같이 수정해 보세요.

package main

import "fmt"

const (
    monday    = "MONDAY"
    tuesday   = "TUESDAY"
    wednesday = "WEDNESDAY"
    thursday
    friday
)

func main() {
    fmt.Println(monday, tuesday, wednesday, thursday, friday)
}

다시 실행해 봅니다.

go run ~/project/const.go

출력 결과는 다음과 같습니다.

MONDAY TUESDAY WEDNESDAY WEDNESDAY WEDNESDAY

여기서 thursdayfriday에는 명시적인 값을 주지 않았습니다. Go 의 규칙에 따라 이들은 이전 상수의 값을 상속받습니다.

  • thursdaywednesday의 값을 가져옵니다.
  • friday 역시 그 앞인 thursday(결국 wednesday) 의 값을 가져옵니다.

이러한 특징은 코드를 간결하게 만들어 주지만, 원리를 모르면 예상치 못한 결과를 초래할 수 있으니 주의해야 합니다.

만약 thursdayfriday에 각기 다른 값을 주고 싶다면 다음과 같이 명시적으로 할당해야 합니다.

const (
    monday    = "MONDAY"
    tuesday   = "TUESDAY"
    wednesday = "WEDNESDAY"
    thursday  = "THURSDAY"
    friday    = "FRIDAY"
)

이렇게 하면 의도한 대로 출력됩니다.

MONDAY TUESDAY WEDNESDAY THURSDAY FRIDAY

iota 상수 생성기

상수를 하나씩 선언하는 것 외에도, Go 에서는 iota를 사용하여 일련의 상수를 간편하게 생성할 수 있습니다. 예제를 통해 확인해 보겠습니다. const.go 파일을 다음과 같이 수정하세요.

package main

import "fmt"

const (
    monday    = iota // 초기값은 0
    tuesday   = iota // 선언될 때마다 1 씩 증가
    wednesday = iota
    thursday  = iota
    friday    = iota
)

func main() {
    fmt.Println(monday, tuesday, wednesday, thursday, friday)
}

실행 결과는 다음과 같습니다.

0 1 2 3 4

iota를 사용하면 첫 번째 항목은 0 부터 시작하며, 이후 항목이 추가될 때마다 자동으로 1 씩 증가합니다.

첫 번째 항목에서 iota를 지정했다면, 이후 항목에서는 iota를 생략해도 자동으로 증가하는 값이 할당됩니다.

package main

import "fmt"

const (
    monday    = iota // 0
    tuesday          // 1
    wednesday        // 2
    thursday         // 3
    friday           // 4
)

func main() {
    fmt.Println(monday, tuesday, wednesday, thursday, friday)
}

만약 특정 숫자를 건너뛰고 싶다면 어떻게 해야 할까요? 이럴 때는 밑줄 (_) 을 사용합니다. 다음 코드는 수요일에 해당하는 값을 건너뛰는 예시입니다.

package main

import "fmt"

const (
    monday  = iota // 0
    tuesday        // 1
    _
    thursday // 3
    friday   // 4
)

func main() {
    fmt.Println(monday, tuesday, thursday, friday)
}

실행 결과는 다음과 같습니다.

go run ~/project/const.go
0 1 3 4

또한 iota는 산술 연산과 함께 사용할 수도 있습니다. const.go에 다음 코드를 입력해 보세요.

package main

import "fmt"

const (
    a = iota     // 0
    b = iota * 3 // 1 * 3 = 3
    c = iota + 4 // 2 + 4 = 6
)

const (
    B  = 1 << (iota * 10) // 1 << (0 * 10) 과 동일
    KB                    // 1024
    MB                    // 1048576
)

func main() {
    fmt.Println(a, b, c)
    fmt.Println(B, KB, MB)
}

실행 결과는 다음과 같습니다.

go run ~/project/const.go
0 3 6
1 1024 1048576

첫 번째 상수 그룹에서는 iota를 이용해 간단한 사칙연산을 수행했습니다.

두 번째 그룹에서는 iota와 비트 왼쪽 시프트 연산자 (<<) 를 결합하여 데이터 단위인 KB 와 MB 를 바이트 (B) 단위로 계산했습니다. 예를 들어 1 KB1024B이고, 1 MB1024 * 10241048576B가 됩니다.

퀴즈

지금까지 배운 내용을 복습해 봅시다. ~/project 디렉토리에 iota.go 파일을 생성하고, iota와 상수를 사용하여 1GB 와 1TB 의 값을 바이트 (B) 단위로 출력하는 프로그램을 작성하세요.

요구 사항:

  1. 변환된 숫자를 직접 입력하여 출력하지 마세요. 반드시 iota를 활용하여 계산해야 합니다.
  2. 파일 이름은 반드시 iota.go여야 하며 ~/project 디렉토리에 위치해야 합니다.

힌트: 앞서 살펴본 "iota" 섹션의 단위 변환 코드를 참고하세요.

최종 출력 형식은 다음과 같아야 합니다.

1GB is equal to 1073741824B
1TB is equal to 1099511627776B

요약

이번 레슨에서 학습한 핵심 내용을 정리해 보겠습니다.

  • 상수는 한 번 선언되면 그 값을 수정할 수 없습니다.
  • 상수는 const 키워드를 사용하여 선언합니다.
  • 여러 상수를 선언할 때는 괄호를 사용하는 방식이 권장됩니다.
  • iota 상수 생성기를 사용하면 연속된 값을 가진 상수를 효율적으로 선언할 수 있습니다.
  • iota는 산술 및 비트 연산과 결합하여 복잡한 계산식에도 활용될 수 있습니다.

우리는 이번 시간을 통해 상수의 기본과 iota 생성기의 강력함을 배웠습니다. 문자열, 정수, 부동 소수점 숫자와 더불어 상수는 Go 프로그래밍을 지탱하는 가장 기초적인 데이터 타입입니다.

✨ 솔루션 확인 및 연습