Go 기본타입과 루프문[2]

Map

Go에서 제공하는 map은 Python의 dictionary나 다른 언어의 Hash Table과 유사하다.

다른 점은, key가 String이 아니어도 된다는 점이다. comparable 타입이라면 모든 데이터 타입이 key가 될 수 있다.

즉, boolean이나 float도 가능하다. 하지만 bool값을 key로 사용하면 2개의 value만 저장할 수 있고, float 값은 프로세서나 OS에 따라 정밀도 이슈가 있을 수 있다.

myMap = make(map[string]int)

// 혹은 이렇게도 가능
myNewMap := map[string]int {
  "key1": 15,
  "key2": 8,
}

Go에서 map을 사용할 때 주의할 점은, map에 없는 값을 key로 가져오면 zero value가 온다는 것이다.

func main() {
	myMap := map[string]int{
		"a": 1,
	}

	fmt.Println(myMap["b"])
    // 0
}

int 값을 value로 가지는 myMap은 없는 값에 접근하면 0을 반환한다.

이렇게 되면, 원래 값이 0인지 빈 값이어서 0이 나온 것인지 알 수 없게 된다.

따라서 아래와 같은 방법으로 검증하면 좋다.

func main() {
	myMap := map[string]int{
		"a": 1,
	}

    val, ok := myMap["b"]
	fmt.Println(ok) // false
	fmt.Println(val) // 0
}

Pointer

포인터는 메모리의 주소다.

*를 통해 포인터가 가리키는 메모리 주소의 값에 접근한다.

포인터로 선언하지 않은 변수의 메모리 주소를 가져오기 위해서는 &를 사용한다.

func getPointer(n *int) {
  *n = *n * *n
}
// 매개변수 n으로는 포인터를 넘기며, 포인터로 넘겨진 변수는 함수가 실행되면 그 값이 갱신된다.

포인터를 사용하면,

  1. 함수 사이에 데이터를 공유할 수 있다.
  2. 0, false 등 zero values를 구분하는 데 유용하다.

상수

Go에서는 const로 상수를 선언한다.

const HEIGHT = 180
const (
  C1 = "123"
  C2 = "abc"
)

const f64 float64 = 1234

var v1 float32 = f64 * 2 // error

상수는 변경불가능하다.

대부분의 경우 암시적으로 타입을 할당하여(타입 명시 없이) 상수를 만들어 사용할 수 있다.

명시적으로 타입을 지정한 경우에는 주의가 필요하다.

위에서 보는 바와 같float64타입의 상수는 float32타입의 변수에 대입할 수 없다.