본문 바로가기
프로그래밍/Golang

Golang: 동일성(Identity) vs 동등성(Equality)

by slowin 2024. 8. 3.

개요

동일성(Identity), 동등성(Equality) 두 개념의 차이점과 Go언어에서의 적용 방법에 대해 알아보겠습니다.

Identity (동일성)

정의

Identity는 두 변수가 메모리 상에서 정확히 같은 객체를 가리키고 있는지를 나타냅니다.

특징

  • 주로 포인터 비교에 사용
  • `==` 연산자로 비교
  • 메모리 주소를 비교

예시

type Person struct {
    Name string
    Age  int
}

p1 := &Person{"Alice", 30}
p2 := &Person{"Alice", 30}
p3 := p1

fmt.Println(p1 == p2) // false (다른 메모리 주소)
fmt.Println(p1 == p3) // true (같은 메모리 주소)

Equality (동등성)

정의

Equality는 두 값의 내용이 같은지를 비교합니다.

특징

  • 값의 내용을 비교
  • 기본 타입에서는 `==` 연산자 사용
  • 복합 타입에서는 `reflect.DeepEqual()` 사용 가능

예시

// 기본 타입
a := 5
b := 5
fmt.Println(a == b) // true

// 구조체
p1 := Person{"Bob", 25}
p2 := Person{"Bob", 25}
fmt.Println(p1 == p2) // true

// 슬라이스 (reflect.DeepEqual 사용)
s1 := []int{1, 2, 3}
s2 := []int{1, 2, 3}
fmt.Println(reflect.DeepEqual(s1, s2)) // true

주의사항

  • 맵, 슬라이스, 함수 비교
    • `==` 연산자로 직접 비교 불가 (컴파일 에러 발생)
      • Golang의 중요한 철학은 코드의 단순함, 명확성과 일관성을 유지합니다.
      • 맵은 구조적으로 복잡하고, 맵의 크기에 따라 상당한 시간이 걸릴 수 있는 작업일 수 있습니다.
      • 이러한 복잡성과 성능 문제를 고려하여, 맵의 직접 비교를 허용하지 않기로 한것이 아닌가 싶습니다.
  • 인터페이스 비교
    • 동적 타입과 값 모두를 비교
  • float 타입 비교
    • 정밀도 문제로 예상치 못한 결과 가능성

정리

1. Identity는 객체의 메모리 주소를 비교하는 반면, Equality는 값의 내용을 비교합니다.
2. 포인터나 참조 타입을 비교할 때는 Identity를 고려해야 합니다.
3. 복합 타입의 내용을 비교할 때는 `reflect.DeepEqual()`을 사용하는 것이 안전합니다.
4. 상황에 따라 적절한 비교 방법을 선택하여 사용해야 합니다.
5. 특수한 경우(맵, 슬라이스, float 등)에는 비교 시 주의가 필요합니다.