1. 할당되지 않은 변수 - zero 값 할당
- bool - fales
- int - 0
- 문자열 - empty string
- 자연스럽게 null object 패턴 적용 가능하다.
2. 리터럴
- 리터럴(literal) = 소스 코드에서 값을 나타내는 표기법
- integer
- 0b, 0o, 0x
- 1_234
- floating
- 6.03e23
- 0x, p (지수)
- rune(문자)
- '와 " 혼용 불가
- 'a', '\141'=8진 숫자, 'x61'=8bt 16진수 숫자, '\u0061'=16bit 16진수 숫자, 'U00000061'=32bit 유니코드
- 8진수 - 권한 플래그, 16진수/이진수 - 비트 필터, 네트워킹, 인프라 응용 프로그램에 사용
- 문자 리터럴
"Greetings and\n\"Salutations\""
`Greetings and
"Salatations"`
- 부동소수점 <-> 정수 리터럴은 상호작용이 가능하다.
- 기본 데이터 타입 기반으로 사용자 정의 타입으로 리터럴을 사용할 수 있다.
- 리터럴은 타입이 지정되어 있지 않다.
- 타입에는 크기 제한이 있다.
3. 정수
- 정수 타입
- int8, int16, int32. int64, uint8, uint16, uint32, uint64
- byte = uint8 (웬만하면 byte 사용)
- int - 32bit CPU에서는 int32, 64bit CPU에서 int64
- 타입을 32bit 부호 있는 정수로 사용하는 64bit 아키텍쳐 중 amd64p32, mips64p32, mips64p32le를 지원한다.
- int <-> int32, int64 간 비교/연산은 컴파일 오류 발생
- uint도 마찬가지
- 정수 리터럴은 기본적으로 int 타입
- rune, uintptr
- int8, int16, int32. int64, uint8, uint16, uint32, uint64
- 사용할 정수 타입 선택하는 방법
- 네트워크 프로토콜(크기/부호가 지정된 정수) 또는 이진 파일 포맷 -> 해당 정수 타입 사용
- 모든 타입을 처리하는 라이브러리 함수 -> int64, uint64 함수 쌍으로 작성
- Go는 제네릭, 함수 오버로딩을 지원하지 않음
- FormatInt
- ParseInt
- 이러면 호출처에서 타입 변환을 해서 함수 전달, 반환된 데이터 다시 변환하면 됨
- 크기가 중요한 패키지 math/bits bits package - math/bits - Go Packages
- 나머지는 int
- 정수 연산자
- https://go.dev/ref/spec#Arithmetic_operators
- 나눗셈은 0 자리 기준으로 아래는 잘린다.
- 비트마스크 연산 제공한다.
4. 부동 소수
- 부동 소수 타입
- float32, float64
- IEEE 754 스펙 사용해서 저장 https://ko.wikipedia.org/wiki/IEEE_754
- 가장 가까운 근사치를 저장한다. (정확하게 표현할 수 없다.)
- 앱실론으로 비교 필요
- float32, float64
5. 복소수
- complex64 : float32를 사용해서 실수부/허수부 표현
- complex128 : float64를 사용 (기본)
x := complex(2.5, 3.1)
y := complex(10.2, 2)
- 함수 출력 타입 판단
- complex로 전달하는 두 값이 float32 -> complex64
- 하나는 float32, 하나는 타입 지정되지 않았으면 -> complex64
- 나머지는 complex64
- 정밀도 제한 문제 - 앱실론으로 비교 필요
- 실수부, 허수부 뽑아내기 위해 real, imag라는 내장 함수 사용
- math/cmplx 패키지에서 complex128 관련 함수 제공
- 허수 리터럴 (복소수 숫자의 허수부) 지원
- 접미사로 i가 붙는다.
- 수치 계산 응용 프로그램 - Gonum 패키지도 있다.
6. 문자열
- 유니코드 지원 -> ==, !=, >, <, + 사용 가능
- 불변 (값 재할당 가능, 변경 불가)
- 룬 = int32의 별칭 (의도를 명확하게 코드에서는 룬 타입을 사용하자)
7. 명시적 타입 변환
- 의도의 명확성, 가독성 중시 - 자동 타입 변환을 허용하지 않음
- 불리언으로 취급 불가, 비교 연산자 사용 필요
- x == 0, s == ""
var x int = 10
var y float64 = 30.2
var z float64 = float64(x) + y1
var d int = x + int(y)
str1 := "hello"
str2 := str1
fmt.Println(str1 == str2) // true
// 두 문자열이 같은 메모리 위치를 가리키는지 확인
fmt.Println(&str1 == &str2) // false
- 관용적인 go는 간결함보다 이해도에 더 가치를 둔다.
8. var VS :=
- := 연산자는 함수 밖에서 사용 불가
- 패키지 레벨에서 변수 선언 - var
- 함수 내에서는 :=
- 예외 (var를 사용해야 하는 경우)
- 제로 값으로 변수 초기화할 때
- 타입 지정
- x := byte(20) 보다는 var x byte = 20 이 관용적이다.
- 섀도잉 변수
func main() {
x := 10
if x > 5 {
fmt.Println(x)
x := 5
fmt.Println(x)
}
fmt.Println(x)
}
- 같은 라인에 여러 변수 선언은 반환된 여러 값을 할당할 때만 하자.
var x2 int
var x3, y3 int = 10, 20
var x4, y4 int
var x5, y5 = 10, "hello"
// 이렇게도 사용 가능하다.
var (
x6 int
y6 = 20
z6 int = 30
d6, e6 = 40, "hello"
f, g string
)
9. const
- go에서 상수는 리터럴에 이름을 부여하는 방법이다.
- 컴파일러가 컴파일 동안 파악할 수 있는 값만 허용된다.
const x9 int64 = 10
const (
idKey = "id"
nameKey = "name"
)
const z9 = 20 * 10
- 상수는 대입문 좌변에 올 수 없다.
- 계산된 값을 변경할 수 없도록 지정하는 방법은 없으나, 언어적으로 변수가 수정되는 것을 제한하므로 불변성은 중요하지 않다고 한다.
- kotlin에서도 똑같다. 개발자의 책임인듯.
10. 타입 지정 상수, 타입 미지정 상수
- 타입 미지정 사수 - 리터럴과 똑같이 처리된다.
- 여러 숫자 타입과 함께 사용할 수 있는 상수 -> 지정하지 않고 유연하게 사용한다.
- 타입 지정 상수 - 해당 타입의 변수에 직접 할당될 수 있다.
- ex) itoa
11. 사용하지 않는 변수
- go 언어의 목표 : 대규모 팀의 쉬운 협업
- 모든 선언된 지역 변수들은 반드시 사용되어야 한다. (아니면 컴파일 오류 발생)
- golangci-lint는 잡아낸다. (패키지 레벨 변수, const 제외)
12. 변수, 상수 이름 짓기
- 카멜 표기법 사용
- go는 패키지 레벨 선언의 이름에서 첫번째 문자의 대소문자 사용으로 패키지 외부에서 접근 가능한지 여부를 결정한다.
- INDEX_COUNTER같은 상수 이름 패턴을 따르지 않는다.
package example
// Exported 함수
func Add(a, b int) int {
return a + b
}
// Unexported 함수
func calculate(a, b int) int {
return a + b
}
- strongly typed 언어이므로 타입 추적을 위한 변수 이름은 필요없다.
- 변수 사용 범위가 적을 수록 변수 이름이 짧아진다.
- 코드 간결하게 한다.
- 추적 힘들시, 너무 많은 일을 한다는 의미이다.
'Language > GoLang' 카테고리의 다른 글
[GopherCon 2021] Go Scheduler (0) | 2024.05.06 |
---|---|
[learning go] 1. 개발환경 설정하기 (0) | 2024.04.06 |