Golang

Golang 입문기 - 문법 4

kahnco 2024. 2. 11. 17:21

서론

 이전 글까지 Golang에서 활용하는 타입에 대해서 공부해보았습니다. 이번 블로그를 끝으로 길고 길었던 타입에 대한 설명에 대한 마지막 투고가 될 것으로 예상합니다.


Properties of types and values


Underlying types (기본 타입들)

각 타입 T 에는 기본 타입들이 있습니다. T가 미리 선언된 Bool, 숫자 또는 문자열 타입 중 하나이거나 리터럴 타입이면 해당 기본 타입은 T 그 자체입니다. 그렇지 않으면 T의 기본 타입T가 선언에서 참조하는 타입기본 타입입니다. 타입 제약 조건의 기본 타입인 타입 매개 변수의 경우 항상 인터페이스입니다.

type (
	A1 = string
	A2 = A1
)

type (
	B1 string
	B2 B1
	B3 []B1
	B4 B3
)

func f[P any](x P) { … }

 

 문자열 A1, A2, B1 및 B2의 기본 유형은 문자열입니다. []B1, B3 및 B4의 기본 유형은 []B1입니다. P의 기본 유형은 interface{} 입니다.


Core types (코어 타입들)

각각의 비 인터페이스 타입 T는 기본 타입 T와 동일한 코어 타입을 갖습니다.

인터페이스 T는 다음 조건 중 하나를 만족하면 코어 타입을 갖습니다.

  1. T의 타입 집합에 있는 모든 타입의 코어 타입인 단일 타입 U가 있습니다.
  2. T의 타입 집합에는 E형 요소가 동일한 채널 타입만 포함되며 모든 방향 채널은 동일한 방향을 갖습니다.
  3. 코어 타입이 있는 다른 인터페이스는 없습니다.

인터페이스의 코어 타입은 충족되는 조건에 따라 다음 중 하나로 결정됩니다.

  1. U형
  2. T형이 오직 양방향 채널들을 포함한 경우에는 chan E 타입이고, 존재하는 방향성 채널의 방향에 따라서 chan<- E 혹은 <-chan E 타입

정의에 따르면 코어 타입은 정의된 타입, 타입 매개 변수 혹은 인터페이스 타입이 아닙니다.

 

 

코어 타입이 있는 인터페이스의 예제:

type Celsius float32
type Kelvin  float32

interface{ int }                          // int
interface{ Celsius|Kelvin }               // float32
interface{ ~chan int }                    // chan int
interface{ ~chan int|~chan<- int }        // chan<- int
interface{ ~[]*data; String() string }    // []*data

 

코어 타입이 없는 인터페이스의 예제:

interface{}                               // no single underlying type
interface{ Celsius|float64 }              // no single underlying type
interface{ chan int | chan<- string }     // channels have different element types
interface{ <-chan int | chan<- int }      // directional channels have different directions

 

일부 연산(슬라이스 표현식, 부록 및 복사)은 byte 슬라이스와 문자열을 허용하는 조금 더 느슨한 형태의 코어 타입에 의존합니다. 특히 인터페이스 T의 타입 집합에 모든 타입의 기본 타입인 []btye와 string의 두 가지 타입이 있으면 T의 코어 타입을 btye string 이라고 합니다.

interface{ int }                          // int (same as ordinary core type)
interface{ []byte | string }              // bytestring
interface{ ~[]byte | myString }           // bytestring

 

btye string은 실제 타입이 아니며 변수를 선언하거나 다른 타입을 구성하는데 사용할 수 없습니다. byte 슬라이스 또는 문자열일 수 있는 byte sequence에서 읽는 일부 연산의 동작을 설명하기 위해서만 존재합니다.


Type identity (타입 일치성)

두 가지 유형은 서로 동일하거나 다를 수 있습니다.

 

명시적으로 명명된 타입은 다른 타입들과는 항상 다릅니다. 그렇지 않다면 두 타입은 기본 타입 리터럴이 구조적으로 동일하다면 동일합니다. 즉, 동일한 리터럴 구조를 가지며 해당 구성 요소가 동일한 타입을 갖는다는 뜻입니다. 자세한 내용은 다음과 같습니다.

  • 두 개의 배열 타입은 요소의 타입이 동일하고 배열의 길이가 동일하면 동일합니다.
  • 두 슬라이스 타입은 요소의 타입이 동일하면 동일합니다.
  • 두 struct 타입은 동일한 필드 순서를 가지며, 해당 필드에 동일한 이름, 동일한 타입 및 동일한 태그가 있으면 동일합니다. 다른 패키지에서 내보내지 않는 필드 이름은 항상 다릅니다.
  • 두 포인터 타입은 기본 타입이 동일하면 동일합니다.
  • 두 함수 타입은 파라미터와 결과 타입들의 개수가 동일하고, 대응하는 파라미터와 결과 타입들이 같고, 두 함수가 모두 변량적이거나 둘다 같지 않으면 일치하지 않습니다.
  • 두 인터페이스 타입은 동일한 타입 집합을 정의하면 동일합니다.
  • 두 map 타입은 키 및 요소 타입이 동일하면 동일합니다.
  • 두 채널 타입이 동일한 요소 타입과 동일한 방향을 가지면 동일합니다.
  • 인스턴스화된 두 타입은 정의된 타입과 모든 타입 인수가 동일하면 동일합니다.

예제를 살펴보면

type (
	A0 = []string
	A1 = A0
	A2 = struct{ a, b int }
	A3 = int
	A4 = func(A3, float64) *A0
	A5 = func(x int, _ float64) *[]string

	B0 A0
	B1 []string
	B2 struct{ a, b int }
	B3 struct{ a, c int }
	B4 func(int, float64) *B0
	B5 func(x int, y float64) *A1

	C0 = B0
	D0[P1, P2 any] struct{ x P1; y P2 }
	E0 = D0[int, string]
)

 

위 예제 중에서 다음 타입들은 동일합니다

A0, A1, and []string
A2 and struct{ a, b int }
A3 and int
A4, func(int, float64) *[]string, and A5

B0 and C0
D0[int, string] and E0
[]int and []int
struct{ a, b *B5 } and struct{ a, b *B5 }
func(x int, y float64) *[]string, func(int, float64) (result *[]string), and A5

 

B0과 B1 은 서로 다른 타입 정의에 의해 생성된 새 타입이므로 다릅니다. func(int, float64) *B0 및 func(x int, y float64) *[]string은 B0과 []string이 다르기 때문에 다르고, P1 및 P2는 서로 다른 타입 매개 변수이기 때문에 다릅니다. D0[int, string] 및 struct{x int; y string}은 전자는 인스턴스화된 정의 타입이고 후자는 타입 리터럴이기 때문에 서로 다릅니다.


Method Sets (메서드 집합)

타입의 메서드 집합은 해당 타입의 피연산자에서 호출할 수 있는 메서드를 결정합니다. 모든 타입에는 해당 메서드와 연결된 (가능하면 빈) 메서드 집합이 있습니다:

  • 정의된 타입 T의 메서드 집합은 수신기 타입 T와 함께 선언된 모든 메서드로 구성됩니다.
  • 정의된 타입 T(T는 포인터도 인터페이스도 아님)에 대한 포인터의 메서드 집합은 수신기 *T 또는 T와 함꼐 선언된 모든 메서드 집합입니다.
  • 인터페이스 타입의 메서드 집합은 인터페이스 타입 집합에서 각 타입의 메서드 집합의 교집합입니다. (결과 메서드 집합은 일반적으로 인터페이스에서 선언된 메서드 집합일 뿐입니다.)
  • 추가 규칙은 구조체 타입에 대한 섹션에서 설명한 대로 임베디드 필드를 포함하는 구조체(및 구조체에 대한 포인터)에 적용됩니다. 다른 모든 타입에는 빈 메서드 집합이 있습니다.

메서드 집합에서 각 메서드에는 고유한 공백이 없는 메서드 이름이 있어야 합니다.

 


결론

드디어 타입에 대한 설명이 얼추 끝났고 다음 글부터는 Block 부터 시작해서 선언과 Scope 에 대한 글을 작성할 예정입니다.

 

반응형

'Golang' 카테고리의 다른 글

Golang 입문기 - 문법 3  (2) 2023.11.20
Golang 입문기 - 문법 2  (2) 2023.10.27
Golang 입문기 - 문법 1  (2) 2023.10.24
Golang 입문기 - 0  (0) 2023.10.20