go의 interface {} (empty interface)는 모든 타입을 담을 수 있습니다.
JAVA, C#의 Object, C 계열 언어의 void* 와 비슷한 용도로 사용됩니다.
interface {}를 사용하다 보면 boxing, unboxing 발생합니다.
package main
import (
"fmt"
"reflect"
"strconv"
)
func main() {
var value1 int = 21
fmt.Printf("main() value1 %x %T\n", &value1, &value1)
Recursion(&value1) // boxing
fmt.Println("")
var value2 string = "21"
fmt.Printf("main() value2 %x %T\n", &value2, &value2)
Recursion(value2) // boxing
fmt.Println("")
}
func Recursion(value interface{}) {
fmt.Printf("Recursion() value: %x %T\n", &value, &value)
vType := reflect.TypeOf(value)
typeKind := vType.Kind()
var n int = 0
if typeKind == reflect.Int {
valueInt, _ := value.(int) // unboxing
fmt.Printf("Recursion() value (%d) is int\n", valueInt)
fmt.Printf("Recursion() int value: %x %T\n", &valueInt, &valueInt)
n = recursion(valueInt)
} else if typeKind == reflect.Pointer {
valueInt := *(value.(*int)) // unboxing
fmt.Printf("Recursion() value (%d) is *int\n", valueInt)
fmt.Printf("Recursion() int value: %x %T\n", &valueInt, &valueInt)
n = recursion(valueInt)
} else if typeKind == reflect.String {
valueString := value.(string) // unboxing
fmt.Printf("Recursion() value (%s) is string\n", valueString)
if i, err := strconv.ParseInt(valueString, 10, 32); err == nil {
n = recursion(int(i))
} else {
n = recursion(1)
}
} else {
fmt.Printf("Recursion() value Type: %s\n", vType.String())
n = recursion(1)
}
fmt.Printf("result %d\n", n)
}
func recursion(n int) int {
if n == 1 || n == 2 {
return 1
} else {
return recursion(n - 1) + recursion(n - 2)
}
}
실행결과>
main() value1 c00000a210 *int
Recursion() value: c000020280 *interface {}
Recursion() value (21) is *int
Recursion() int value: c00000a218 *int
result 10946
main() value2 c000020290 *string
Recursion() value: c0000202b0 *interface {}
Recursion() value (21) is string
result 10946
아래 소스코드는 새로 추가된 generic으로 수정된 내용입니다.
package main
import (
"fmt"
"strconv"
"golang.org/x/exp/constraints"
)
func main() {
var value1 int = 21
fmt.Printf("main() value1 %x %T\n", &value1, &value1)
Recursion(value1)
fmt.Println("")
var value2 string = "21"
fmt.Printf("main() value2 %x %T\n", &value2, &value2)
RecursionByString(value2)
fmt.Println("")
}
func Recursion[T constraints.Integer | constraints.Float](value T) {
n := recursion(int(value))
fmt.Printf("result %d\n", n)
}
func RecursionByString(value string) {
var n int = 0
if i, err := strconv.ParseInt(value, 10, 32); err == nil {
n = recursion(int(i))
} else {
n = recursion(1)
}
fmt.Printf("result %d\n", n)
}
func recursion(n int) int {
if n == 1 || n == 2 {
return 1
} else {
return recursion(n - 1) + recursion(n - 2)
}
}
실행결과>
main() value1 c00000a210 *int
result 10946
main() value2 c000020290 *string
result 10946
리턴값없는 함수 제네릭 사용할 수 있습니다.
func 함수명[T constaint](value1 T)
타입 파라미터: [T constaint]
제네릭은 여러 개의 파라미터와 함수 인자값도 사용할 수 있습니다.
func GenericPrint[T1 any, T2 any](value1 T1, value2 T2) {
fmt.Println(value1, value2)
}
func Add[T any](value1, value2 T) T {
return value1 + value2
}
'golang' 카테고리의 다른 글
golang windows service (0) | 2025.01.05 |
---|---|
golang smtp email send (0) | 2025.01.05 |
golang gzip 압축 해제 (0) | 2024.10.06 |
golang brotli 브로틀리 압축 해제 (0) | 2024.10.06 |
golang gzip 압축 (0) | 2024.10.01 |