利用GO中的仿制药的力量:综合指南 - 第一部分
#编程 #go #generics

介绍

go,由于其简单性,效率和并发功能而获得了广泛的知名度。但是,很长一段时间以来缺少的一个关键功能是通用。通用编程使开发人员能够编写可以与不同数据类型一起使用的代码,从而使代码更加灵活,可重复使用且易于错误。随着GO 1.18的引入仿制药,该语言取得了巨大的飞跃,使开发人员能够以更高的优雅和效率来解决复杂的问题。在这篇博客文章中,我们将在GO中深入了解仿制药的世界,并探索这一新功能如何彻底改变我们编写代码的方式。

需要通用

在GO引入通用物之前,开发人员必须依靠接口或编写特定于类型的代码来处理各种数据类型。尽管接口允许一定程度的抽象,但他们经常引入性能开销,并强迫开发人员妥协类型的安全性。此外,在处理多种数据类型时,代码重复很常见,导致可维护性挑战。

仿制药通过启用与任何类型一起使用的功能,数据结构和算法的创建,同时保持严格的类型安全性,以解决这些限制。这意味着开发人员可以编写一次代码并将其应用于多种数据类型,从而导致更清洁,更可维护和高效的程序。

类型参数和类型约束

仿制药的核心是类型参数,它们是通用功能或数据结构中使用的特定类型的占位符。
现在允许功能和类型具有类型参数。类型参数列表看起来像普通参数列表,除了它使用方括号代替括号。

要展示它的工作原理,让我们从浮点值的基本非生成最小函数开始:

func Min(x, y float64) float64 {
    if x < y {
        return x
    }
    return y
}

上面的函数Min()仅适用于浮动类型值。为了计算整数的最小(),您需要编写单独的功能(或使用接口)。

我们可以通过添加类型参数列表来使此函数通用使其适用于不同类型。在此示例中,我们添加了一个类型参数t的类型参数列表,然后用T.
替换float64的用途

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

func GMin[T constraints.Ordered](x, y T) T {
    if x < y {
        return x
    }
    return y
}

现在可以通过编写像

这样的呼叫来调用此函数来调用此函数

x := GMin[int](2, 3)
y := GMin[float64](2.1, 3.1)

类型约束在使用仿制药时确保类型安全性中起着至关重要的作用。通过指定约束,开发人员限制了可以与通用函数一起使用的类型,防止滥用并在编译过程中提供更好的错误消息。

在通用GMIN实现中,类型约束是从约束软件包获得的。
constraints.Ordered是一种类型约束。

具体而言,有序约束负责定义可以订购值的类型集,即使用诸如<,<=,>等的操作员进行比较。此约束保证只能使用具有可比值的类型在Gmin中。

重要的是要注意,在GO中,类型约束必须作为接口实现。

我们现在以新的方式查看界面。
直到最近,GO规格说一个接口定义了一个方法集,该方法集大约是接口中列举的一组方法。任何实现所有这些方法实现接口的类型。

Go Interfaces

您现在可以在接口中定义类型设置。例如,接口{int | string | bool}定义包含类型int,string和bool的类型集。

type-sets

另一种说法的方式是,仅通过int,string或bool来满足此界面。
现在让我们看一下约束的实际定义。有序:

type Ordered interface {
    Integer|Float|~string
}

该声明说有序接口是所有整数,浮点和字符串类型的集合。垂直条表示类型的结合。整数和浮点是在约束软件包中类似定义的接口类型。请注意,没有订购接口定义的方法。

现在,让我们看一个简单的示例,其中func SumIntsOrFloats是一个通用函数,总和映射m的值。它支持两种类型INT64和Float64的值。

package main

import (
    "fmt" 
)

// SumIntsOrFloats sums the values of map m. It supports both int64 and float64
// as types for map values.
// K avd V are type params
// comparable = type constraint (built in)
// Number = type constraint
type Number interface {
    int64 | float64
}

func SumIntsOrFloats[K comparable, V Number](m map[K]V) V {
    var s V
    for _, v := range m {
        s += v
    }
    return s
}

func main() {
    // Initialize a map for the integer values
    ints := map[string]int64{
        "first":  34,
        "second": 12,
    }

    // Initialize a map for the float values
    floats := map[string]float64{
        "first":  35.98,
        "second": 26.99,
    }
    fmt.Printf("Generic Sums: %v and %v\n",
    SumIntsOrFloats(ints),
    SumIntsOrFloats(floats))
}
go run main.go 
Generic Sums: 46 and 62.97

好吧,这就是这个博客中的仿制药。我们将在即将到来的博客中深入研究仿制药,并查看更多用例。

如果您想讨论有关GO的任何事情,请与我联系! :D
Twitter -https://twitter.com/im_rsawra
LinkedIn - https://www.linkedin.com/in/rahul-sawra/

参考:

  1. https://go.dev/blog/intro-generics
  2. https://youtu.be/Pa_e9EeCdy8