[2012-05-21 翻译自这里, 对原文有所扩展, 也有所删减. 版权属于原作者, 转载必须保留此声明.]
在进入泛型的话题之前, 首先实现对int slice(可以看做int数组)的冒泡排序:
func BubbleSort(array []int) {
for i := 0; i < len(array); i++ {
for j := 0; j < len(array)-i-1; j++ {
if array[j] > array[j+1] {
// 交换
array[j], array[j+1] = array[j+1], array[j]
}
}
}
}
如你所见, 上面的代码仅适用于对int数组进行排序, 如果想要对string数组排序, 不得不另写一个.
是否可以只写一个通用的泛型程序, 以便对所有类型的数组(甚至是任意数据)进行冒泡排序?
很遗憾, go不支持java中的标记式泛型. 但是我们可以使用go的interface实现类似的功能.
interface用于定义方法的集合. 在冒泡排序中, 我们可以将排序操作分解成3个方法: Len()方法负责计算长度, Less(i, j)方法负责比较大小, Swap(i, j)方法负责进行交换.
// 定义可排序接口
type Sortable interface {
Len() int
Less(int, int) bool
Swap(int, int)
}
可以说, 任何实现了Sortable接口的数据类型都可进行冒泡排序, 下面是对Bubblesort方法的改造:
func BubbleSortable(arr Sortable) {
length := arr.Len()
for i := 0; i < length; i++ {
for j := i; j < length-i-1; j++ {
if arr.Less(j, j+1) {
arr.Swap(j, j+1)
}
}
}
}
BubbleSortable函数可以对所有Sortable类型的数据进行排序. 那么, 哪些数据是Sortable类型的呢? 很简单, 那些实现了Len(), Less(i, j), Swap(i, j)方法的数据类型都是Sortable的.
如果想要对int数组进行冒泡排序, 只需让int数组实现以上3个方法即可:
// 定义IntArr类型
type IntArr []int
// 给IntArr提供Len方法
func (arr IntArr) Len() int {
return len(arr)
}
// 给IntArr提供Less方法
func (arr IntArr) Less(i int, j int) bool {
return arr[i] < arr[j]
}
// 给IntArr提供Swap方法
func (arr IntArr) Swap(i int, j int) {
arr[i], arr[j] = arr[j], arr[i]
}
至此, 我们定义了新的类型: IntArr(实际上就是int数组), 并为IntArr增加了Len, Less, Swap方法.
注意, 在go中, 实现接口不需要像java那样显式的说明对某个接口的implements, 只需要为类型提供所有interface中定义的方法即可. 此例中, 我们给IntArr提供了所有Sortable中定义的方法, 所以IntArr已经实现了Sortable接口. 接下来要做的是将IntArr类型的数据传递给BubbleSortable函数就可以了:
intarr := IntArr{2, 3, 1, -9, 0}
// 调用排序方法
BubbleSortable(intarr)
// 输出排序之后的数据
fmt.Printf("sorted int arr is: %v\n", intarr)
同样的, 如果想对string数组进行冒泡排序, 也只需要让string数组实现Sortable接口中定义的所有方法:
type StrArr []string
func (arr StrArr) Len() int {
return len(arr)
}
func (arr StrArr) Less(i int, j int) bool {
return arr[i] < arr[j]
}
func (arr StrArr) Swap(i int, j int) {
arr[i], arr[j] = arr[j], arr[i]
}
测试代码如下:
strarr := StrArr{"nut", "ape", "elephant", "zoo", "go"}
Bubblesort(strarr)
fmt.Printf("sorted string arr is: %v\n", strarr)
现在, 你可以对任意数据进行冒泡排序了, 只需要该类型实现了Len, Less, Swap方法.
分享到:
相关推荐
Grizzly是一个专门为Go语言设计的集合库,它提供了类似Java或其他支持泛型的语言中的功能,如Map、Filter、Find等,使开发者能在不依赖泛型的情况下更方便地操作数据。 Grizzly库的核心理念是提供一种类型安全的...
通过以上示例可以看出,虽然 Go 语言在 Go 1.18 之前没有内置的泛型支持,但通过使用接口和反射技术,开发者仍然可以实现类似泛型的功能,以提高代码的灵活性和复用性。这种方法对于希望在不使用最新版本 Go 语言的...
在Go编程语言中,处理来自各种来源的数据,如JSON、XML或自定义协议时,将这些数据转换为Go结构体是常见的需求。`go-mapstructure`库提供了解决这一问题的有效工具,它允许我们将泛型的`map[string]interface{}`类型...
在Go 1.18版本之前,Go语言并没有内置泛型,这使得开发者在编写通用代码时需要使用接口或类型断言等技巧来实现类似的功能。Go 1.18引入了泛型,使得编写高效且灵活的代码变得更加容易。泛型允许我们在定义一个类型...
标题“Go-Package generics is the true way to program generically in golang”强调了在Go中使用泛型包进行泛型编程的重要性。描述中的“Package generics”暗示我们将探讨的是Go标准库或第三方库中的一个特定包,...
samber/lo 是一个基于 Go 1.18+ 泛型的 Lodash 风格的 Go 库。...将来,5 到 10 个助手将与 Go 标准库中的助手重叠(在包名称 slices 和 maps 下)。我觉得这个库是合法的,并且提供了许多更有价值的抽象。
在Go语言中,泛型是自Go 1.18版本起引入的一项重要特性,它极大地增强了代码的可复用性和灵活性。这个“基于Go 118泛型映射过滤器的Lodashstyle Go库”显然是为了提供类似于JavaScript中的Lodash库功能,通过泛型...
Go语言本身并不原生支持泛型,但gomacro提供了一种机制,使得在解释器中可以模拟泛型的效果。这使得开发者能够在不修改原始代码的情况下,尝试不同类型的参数,从而验证代码的通用性。这对于理解和优化代码的复用性...
1. **泛型提案**:项目可能包含了一份关于如何在Go中实现泛型的详细提案,这可能包括设计目标、语法示例、性能预期以及与其他语言泛型机制的对比。 2. **代码实现**:gomodule-master目录下的源代码可能是实现该...
开源项目-golang-go.zip是一个与Go编程...总之,开源项目-golang-go.zip中的内容可能涉及对Go语言泛型编程设施的探讨和实现,这将对Go语言的未来发展产生重大影响,使Go开发者能够利用泛型的优势,提高代码质量和效率。
Go泛型示例代码go-generics-example用法$ go build -gcflags = -G = 3要求Go 1.17或更高版本广告进入Go语言的泛型为我们带来了什么?又名mattn)
基础go仓库,基于1.18 workspace和泛型支持Go语言(也称为Golang)是由Google开发的一种静态强类型、编译型的编程语言。它旨在成为一门简单、高效、安全和并发的编程语言,特别适用于构建高性能的服务器和分布式系统...
这个开源项目对于那些对Go语言泛型感兴趣的开发者来说,是一个宝贵的学习资源。通过它的源码,我们可以了解泛型在实际项目中的应用,以及在性能和抽象之间的权衡。同时,它也为那些希望在自己的项目中使用泛型的...
3. **类型约束**:在 Go 的泛型中,类型约束是定义泛型函数或类型的类型参数必须遵循的规则。GenX 可能包含了一套自定义的类型约束,确保了泛型使用的正确性。 4. **编译时检查**:由于 Go 语言的静态类型特性,...
结构(Struct)在某些语言中类似于C#或Go中的struct,它是包含多个字段的对象,每个字段有其特定的类型。在PHP中,我们可以使用类来模拟结构,通过在类中定义私有属性并提供getter和setter来操作这些属性。如果`...
最后,可以在设置的工作目录中编写Go语言源代码文件,并使用Go命令来编译和执行这些文件。 在Go语言的开发环境中,编写源代码文件是核心部分。编写Go程序通常从一个main函数开始,这是每个可执行Go程序的入口点。Go...