为了账号安全,请及时绑定邮箱和手机立即绑定

如何编写接受任何数值类型的泛型函数?

如何编写接受任何数值类型的泛型函数?

Go
函数式编程 2022-09-26 14:54:35
来自JS / TS,我想结帐并制作一个简单的计算器,因为int和浮点数之间存在差异,因此编写需要任何数字的函数的首选方法是什么?例如:package mainfunc add(a float64, b float64) float64 {  return a + b;}func main() {  a := 1;  b := 2;  fmt.Println(add(1, 2)); // 3  fmt.Println(add(a, b)); // cannot use a (type int) as type float64 in argument to add  fmt.Println(add(1.5, 3.2)); // 4.7  fmt.Println(add(2.5, 2)); // 4.5}我是否需要将所有内容转换为浮点型(因为它“覆盖”了int范围),或者我是否为每个类型创建一个单独的函数,例如和,或者可能有一种更优雅的方式?addInt(a int, b int) intaddFloat(a float64, b float64) float64
查看完整描述

2 回答

?
慕村225694

TA贡献1880条经验 获得超4个赞

前往 1.18


通过在 Go 1.18 中引入类型参数,这更容易实现。


您可以定义 一个参数化的函数,并使用接口约束来限制为数值类型。TT


func add[T Number](a, b T) T {

    return a + b

}

可以使用 golang.org/x/exp/constraints 包(仍处于实验阶段)来定义约束:Number


import "golang.org/x/exp/constraints"


type Number interface {

    constraints.Integer | constraints.Float

}

哪里:


Number是 和 的类型集的并集constraints.Integerconstraints.Float

constraints.Integer是所有有符号和无符号整数类型的集合

contraints.Float是浮点型的集合

这将允许您使用任意两个数值类型的参数进行调用。然后,在函数体中,您将能够使用约束中所有类型支持的任何操作。因此,对于数字,这也包括算术运算符。然后声明类似的函数很容易:add


func multiply[T Number](a, b T) T {

    return a * b

}

请记住,参数必须具有相同的类型。无论泛型如何,您都不能使用不同的类型;从规格运营商:


[...]操作数类型必须相同,除非操作涉及移位或非类型化常量。


因此,我们的泛型和函数仅使用一个类型参数定义。这意味着您也不能使用默认类型不兼容的非类型化常量调用函数:addmultiplyTadd


add(2.5, 2) // won't compile

在这种情况下,编译器将从第一个参数推断出 的类型,该参数默认为 ,然后将无法匹配 的类型,该类型默认为 。T2.5float642int


完整程序:


package main


import (

    "fmt"


    "golang.org/x/exp/constraints"

)


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

    // fmt.Println(add(2.5, 2)) // default type int of 2 does not match inferred type float64 for T

}


func add[T Number](a, b T) T {

    return a + b

}

游乐场: https://go.dev/play/p/rdqi3_-EdHp


查看完整回答
反对 回复 2022-09-26
?
catspeake

TA贡献1111条经验 获得超0个赞

直到 Go 1.17(预泛型)。查看更新解决方案的其他答案


最简单的选择是在调用站点上转换参数。

add(float64(a), float64(b))


查看完整回答
反对 回复 2022-09-26
  • 2 回答
  • 0 关注
  • 59 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信