Есть ли вариант в Golang отработать типы через interface{}?
Можно ли как-то в Го операцию сложения сделать одной строкой без определения типа? Понимаю, что нужно a.(uint64) + b.(uint64) указывать, но вдруг есть способ автоопределения типа?
func f (a interface{}, b interface{}) interface{} {
return a + b
}
a := uint64(100)
b := float64(200)
c := f (a, b)
Ответы (2 шт):
Нет, в Go такого нет - это не динамический язык..
Можно либо определять тип и приводить его к желаемому через reflection, либо ждать Go 1.18 и реализовать вашу функцию через generic-ки.
ответ не простой.
в версиях Го до 1.18 нужно кастить в тип данных, что не очень. А вот с 1.18 версии появляются дженерики. Уже вышла версия go1.18rc1
Определяем функицю, параметризованную T, используя constraint для ограничения типов у T
import "constraints"
type Number interface {
constraints.Integer | constraints.Float
}
func add[T Number](a, b T) T {
return a + b
}
получается, что
Number- наш тип, аля множествоconstraints.Integerиconstraints.Floatconstraints.Integer- просто целочисленные типы данныхcontraints.Float- с плавающей точкой
Это позволит нам вызывать add с любыми двумя аргументами Number типа. Тогда в теле функции мы сможем использовать любую операцию, которая поддерживается всеми типами. Например, умножение, как в вашем примере
func multiply[T Number](a, b T) T {
return a * b
}
Конечно, тут тоже есть ограничение: аргументы должны иметь один и тот же тип. Независимо от дженериков, вы не можете использовать разные типы. вот из спецификаций Operators:
[...] the operand types must be identical unless the operation involves shifts or untyped constants.
то есть следующий пример не будет работать
add(2.5, 2)
потому что компилятор определит тип T из первого аргумента 2.5, который по умолчанию равен float64, а затем не сможет сопоставить тип 2, который по умолчанию равен int.
package main
import (
"constraints"
"fmt"
)
type Number interface {
constraints.Integer | constraints.Float
}
func main() {
a := 1
b := 2
fmt.Println(add(1, 2)) // 3
fmt.Println(add(a, b)) // 3
fmt.Println(add(1.5, 3.2)) // 4.7
}
func add[T Number](a, b T) T {
return a + b
}