Tucker의 Go 언어 프로그래밍 책과 유튜브를 통해 학습 중입니다.
인터페이스(Interface)와 타입 제한자 차이
- 하나의 Interface가 있고, String() 메서드를 가지고 있으면 이는 string 타입들을 다 해당 Interface로 사용될 수 있음.
tpye Stringer interface {
String() string
}
- 타입 제한은, 동일하게 interface라고 사용하지만 틸드(~)를 사용하여 정의된 타입들 중 하나가 가능함.
tpye Integer interface {
~int8 | ~int16 | ~int32 | int64 | ~int
}
→ 같은 키워드인 인터페이스를 동일하게 사용하였지만, 둘 다 타입을 제한하는 목적으로 사용한다고 볼 수 있음.
- 인터페이스는 해당 조건에 정의된 메서드를 포함한 타입만 해당 인터페이스로 가능함. = 타입 제한 목적
- 타입 제한자는 포함된 타입들 중 하나만 가능하다라는 의미. = 타입 제한 목적
✓ 엄연하게 둘은 다르기 때문에 쓰임이 완전히 다름.
package main
import (
"fmt"
"hash/fnv"
)
type ComparableHasher interface {
comparable // 같다(==)와 다르다(!=) 가능
Hash() uint32
}
type MyString string
func (s MyString) Hash() uint32 {
h := fnv.New32a()
h.Write([]byte(s))
return h.Sum32()
}
func Equal[T ComparableHasher](a, b T) bool {
if a == b {
return true
}
return a.Hash() == b.Hash()
}
func main() {
var s1 MyString = "Hello"
var s2 MyString = "World"
fmt.Println(Equal(s1, s2))
}
// 결과
false
- ComparableHasher라는 이름 타입 제한을 정의하고, comparable은 ==,!= 를 지원함.
Go 내부 타입 제한으로 Hash() uint32 메서드를 포함하도록 제한함.
따라서, 해당 이름 타입은 같다와 같지 않다를 지원하고 Hash() uint32 메서드를 포함한 타입만 가능함.
- MyString이란, string 별칭 타입을 정의하고, Hash32 uint32 메서드를 포함하도록 함.
MyString은 ComparableHasher 제한에 만족한 타입이 됨.
- ComparableHasher 제한을 사용하는 Equal()이라는 제네릭 함수를 정의함.
먼저 == 연산자로 둘이 같은지 확인하고, 만약 다를 경우 Hash() 메서드 호출 결과로 다시 한번 확인해서 같은지 확인함.
→ 타입 제한에 일반 인터페이스와 같이 특정 메서드를 포함하도록 제한을 추가할 수 있음.
※ 타입 제한은 제네릭 프로그래밍의 타입 파라미터에서만 사용될 수 있고 일반 인터페이스처럼 사용할 수 없음.
func Equal(a, b ComparableHasher) bool { // Error
ComparableHasher 타입 제한을 포함하고 있기 때문에 인터페이스 처럼 사용할 수 없어 에러가 발생함.
타입 제한을 포함한 인터페이스는 반드시 타입 파라미터로 정의되어야 함!
func Equal[T ComparableHasher](a, b T) bool { // OK
package main
import (
"fmt"
"strconv"
"strings"
)
func Map[F, T any](s []F, f func(F) T) []T {
rst := make([]T, len(s))
for i, v := range s {
rst[i] = f(v)
}
return rst
}
func main() {
doubled := Map([]int{1, 2, 3}, func(v int) int {
return v * 2
})
// 각 값을 두 배씩 증가시키는 슬라이스
uppered := Map([]string{"hello", "world", "abc"}, func(v string) string {
return strings.ToUpper(v)
})
// 대문자로 변경하는 슬라이스
tostring := Map([]int{1, 2, 3}, func(v int) string {
return "str" + strconv.Itoa(v)
})
// 문자열로 변경하는 슬라이스
fmt.Println(doubled)
fmt.Println(uppered)
fmt.Println(tostring)
}
// 결과
[2 4 6]
[HELLO WORLD ABC]
[str1 str2 str3]
- Map() 제네릭 함수를 정의하고, F와 T 두 개의 타입 파라미터가 있고, 이 모두는 모든 타입을 사용할 수 있음.
함수 인수 두 개를 받는데 첫 번 째 인수는 F타입 슬라이스이고, 두 번째 인수는 함수 타입으로 F 타입 값을 받아 T 타입 값을 반환
Map() 함수는 s 슬라이스의 각 요소를 두 번째 인수인 f 함수를 사용해 변환한 새로운 슬라이스를 반환함.
- Map() 함수를 이용해 int 슬라이스의 각 값을 두 배씩 증가시키는 새로운 슬라이스를 만듦.
- Map() 함수를 이용해 string 슬라이스의 각 요소를 대문자로 변경하는 새로운 슬라이스를 만듦.
- Map() 함수를 이용해 int 슬라이스의 각 값을 문자열로 변경하는 새로운 슬라이스를 만듦.
'Language > Golang' 카테고리의 다른 글
Golang (Go언어) Go로 만드는 웹 (1) (0) | 2025.01.02 |
---|---|
Golang (Go언어) 제네릭 프로그래밍(Generic Programming) 3/3 (0) | 2025.01.01 |
Golang (Go언어) 제네릭 프로그래밍(Generic Programming) 1/3 (1) | 2024.12.27 |
Golang (Go언어) 채널과 컨텍스트(Channel & Context) (0) | 2024.12.11 |
Golang (Go언어) Go루틴 (0) | 2024.12.07 |