목차
상수란
상수는 변하지 않는 값을 말한다.
- 정수, 실수, 문자열 등 기본 타입값들만 상수로 선언될 수 있다.
- 구조체, 배열 등 기본 타입(primitive)이 아닌 타입(complex)
- 상수명의 규칙은 변수명과 같다.
- 첫 글자가 대문자인 상수는 패키지 외부로 공개되는 상수이다.
- 값으로만 동작하기 때문에 대입문의 좌변에 올 수 없다.
- 상수는 값, 이름, 타입 3 가지 속성만 가진다.
상수로 사용될 수 있는 타입
- 불리언
- 룬(rune)
- 정수
- 실수
- 복소수
- 문자열
선언 방식
const ConstValue int = 10
- const : 상수 선언 키워드
- ConstValue : 상수명
- int : 타입
- 10 : 값
package main
import "fmt"
func main() {
const C int = 10 // ❶ 상수 선언
var b int = C * 20 // ❷ 대입문 우변에 값으로 동작합니다.
C = 20 // ❸ 에러 발생 - 상수는 대입문 좌변에 올 수 없습니다.
fmt.Println(&C) //
}
- & 연산자를 변수앞에 사용하면 그 변수의 메모리 주솟값을 반환하지만 상수 앞에 사용하면 상수의 메모리 주솟값을 접근할 수 없기 때문에 출력하면 에러가 발생한다.
그래서 상수는 언제쓰나?
- 변하면 안되는 값
- 코드값을 통해서 숫자에 의미를 부여할 때
1️⃣ 변하면 안되는 값
package main
import "fmt"
func main() {
const PI1 float64 = 3.141592653589793238 // ❶
var PI2 float64 = 3.141592653589793238 // ❷
// PI1 = 4 // ❸
PI2 = 4 // ➍
fmt.Printf("원주율: %f\\n", PI1)
fmt.Printf("원주율: %f\\n", PI2) // ➎
}
---
원주율: 3.141593
원주율: 4.000000
원주율은 변하지 않는 불변의 값이다.
- 변수로 선언된 값은 컴파일 단계에서 4로 바뀌어 출력되었다.
이렇듯 상수를 사용하면 의도치 않은 결과를 미연에 방지할 수 있다.
❓ 코드값이란?
코드값이란 어떤 숫자에 의미를 부여하는 것을 말한다.
- ASCII 문자 코드에서 ‘A’는 65이다.
- HTTP의 Status Code인 200은 OK이다.
- HTTP의 Status Code인 404는 Not Found이다.
200번과 404번 숫자 자체에 어떤 의미가 있는게 아니고 통신을 편하게 하기 위하여 숫자값에 의미를 부여한 것이다.
프로그래밍에서도 이런 코드를 사용해야 하는 경우가 많음.
다음과 같이 문자열로 나타낼 수 있지만 번거롭고, 스펠링도 틀릴 수도 있다. 또한 문자열 처리가 숫자값 보다 성능이나 메모리에 더 안좋은 문제가 있다.
animal := "Pig"
따라서 아래처럼 동물에 숫자를 지정하여 숫자에 의미를 부여하는 코드로 처리하면 더욱 편리하다.
Pig int = 1
Cow int = 2
2️⃣ 코드값으로 사용하기
package main
import "fmt"
// ❶ 상수값에 코드를 부여합니다.
const Pig int = 0
const Cow int = 1
const Chicken int = 2
// ❸ 코드값에 따라서 다른 텍스트를 출력합니다.
func PrintAnimal(animal int) {
if animal == Pig {
fmt.Println("꿀꿀")
} else if animal == Cow {
fmt.Println("음메")
} else if animal == Chicken {
fmt.Println("꼬끼오")
} else {
fmt.Println("...")
}
}
func main() {
// ❷ PrintAnimal() 함수를 호출하여 동물 소리를 출력합니다.
PrintAnimal(Pig)
PrintAnimal(Cow)
PrintAnimal(Chicken)
}
iota로 간편하게 열거값 사용하기
코드값으로 사용하기 때문에 값이 그냥 1, 2, 3, … 처럼 1씩 증가하도록 정의할 때 iota 키워드를 사용하면 편리하다.
- iota는 0부터 시작하여 1씩 증가한다.
- iota는 소괄호를 벗어나면 다시 초기화된다.
아래의 코드에서 빨강, 파랑, 초록 세 색에 숫자 코드를 부여하기 때문에 어떤 숫자가 사용되는지는 의미가 없다.
const (
Red int = iota // 1
Blue int = iota // 2
Green int = iota // 3
)
1️⃣ iota 생략
만약, 첫 번째 값과 똑같은 규칙이 계속 적용된다면 타입과 iota를 생략할 수 있다.
const (
C1 uint = iota + 1 // 0 + 1
C2 // 1 + 1
C3 // 2 + 1
)
2️⃣ bit flag 사용
const (
C1 uint = 1 << iota // 1 = 1 << 0
C2 // 2 = 1 << 1
C3 // 4 = 1 << 2
)
타입 없는 상수
상수 선언 시 타입을 명시하지 않을 수 있다.
- 타입이 정해져 있지 않은 상황에서 사용할 수 있다.
package main
import "fmt"
const PI = 3.14 // ❶ 타입 없는 상수
const FloatPI float64 = 3.14 // ❷ float64 타입 상수
func main() {
var a int = PI * 100 // ❸ 오류 발생하지 않습니다.
var b int = FloatPI * 100 // ➍ 타입 오류 발생
fmt.Println(a)
fmt.Println(b)
}
타입 없는 상수는 변수에 복사될 때 타입이 정해지기 때문에 여러 타입에 사용되는 상숫값을 사용할 때 편리하다.
상수와 리터럴
리터럴은 고정된 값, 값 자체로 쓰인 문구라고 볼 수있다.
var str string = "Hello World"
var i int = 0
i = 30
위 코드에서는 "Hello World", 0, 30과 같이 고정된 값 그 자체로 쓰인 Value 값이 리터럴이다.
- Go 언어에서 상수는 리터럴과 같이 취급한다.
- 그래서 컴파일 될 때 상수는 리터럴로 변환되어 실행파일에 쓰인다.
- 상수 표현식 역시 컴파일 타임에 실제 결괏값 리터럴로 변환하기 때문에 상수 표현식 계산에 CPU 자원을 사용하지 않는다.
- 상수의 메모리 주솟값에 접근할 수 없는 이유 역시 컴파일 타임에 리터럴로 전환되어 실행파일에 값 형태로 쓰이기 때문이다.
- 그래서 동적 할당 메모리 영역을 사용하지 않는다.
'Programming > Go' 카테고리의 다른 글
[Golang] Switch문 (0) | 2022.11.06 |
---|---|
[Golang] if문 (0) | 2022.11.06 |
[Golang] 함수 (Function) (1) | 2022.10.29 |
[Golang] 연산자 (Operator) (0) | 2022.10.29 |
[Golang] 표준 입출력 (0) | 2022.10.23 |