go tour泛型
5 泛型
类型参数
s
是满足内置约束comparable
的任何类型T
的切片。x
也是相同类型的值。comparable
是一个有用的约束,它能让我们对任意满足该类型的值使用==
和!=
运算符。
func Index[T comparable](s []T, x T) int
// Index 返回 x 在 s 中的下标,未找到则返回 -1。
func Index[T comparable](s []T, x T) int {for i, v := range s {// v 和 x 的类型为 T,它拥有 comparable 可比较的约束,// 因此我们可以使用 ==。if v == x {return i}}return -1
}func main() {// Index 可以在整数切片上使用si := []int{10, 20, 15, -10}fmt.Println(Index(si, 15))// Index 也可以在字符串切片上使用ss := []string{"foo", "bar", "baz"}fmt.Println(Index(ss, "hello"))
}2
-1
练习 泛型类型
作为练习,请为此链表的实现添加一些功能。
- 用全局函数
Add
和Delete
,传递双指针**List[T]
,避免方法接收者语法问题。 - 给
T
加comparable
约束,保证可以用==
。 - 其他方法(如
Find
、Traverse
)仍然用方法接收者*List[T]
,这样intList.Traverse()
能正常调用。 - 无比较使用T any。有比较操作使用T comparabel
package mainimport "fmt"// List 表示一个可以保存任何类型的值的单链表。
type List[T any] struct {next *List[T]val T
}// NewList 创建一个新的空链表(返回头指针为 nil)
func NewList[T any]() *List[T] {return nil
}// Add 在链表末尾添加一个节点
func Add[T any](l **List[T], value T) {newNode := &List[T]{val: value}if *l == nil {*l = newNode} else {current := *lfor current.next != nil {current = current.next}current.next = newNode}
}// Delete 删除链表中第一个值等于 value 的节点
func Delete[T comparable](l **List[T], value T) {if *l == nil {return}if (*l).val == value {*l = (*l).nextreturn}current := *lfor current.next != nil && current.next.val != value {current = current.next}if current.next != nil {current.next = current.next.next}
}// Find 查找链表中第一个值等于 value 的节点
func Find[T comparable](l *List[T], value T) *List[T] {current := lfor current != nil {if current.val == value {return current}current = current.next}return nil
}// Traverse 遍历链表并打印每个节点的值
func Traverse[T any](l *List[T]) {current := lfor current != nil {fmt.Print(current.val, " ")current = current.next}fmt.Println()
}//链表长度
func Len[T any](l *List[T]) int {current := lcount:=0for current != nil {count++current = current.next}return count
}func Reverse[T any](l *List[T]) *List[T] {var newHead *List[T] = nilcurrent := lfor current != nil {next := current.nextcurrent.next = newHeadnewHead = currentcurrent = next}return newHead
}func main() {// 示例:创建 int 类型链表并操作var intList *List[int] = NewList[int]()Add(&intList, 1)Add(&intList, 2)Add(&intList, 3)fmt.Print("链表内容: ")Traverse(intList) // 输出: 1 2 3found := Find(intList, 2)if found != nil {fmt.Println("找到节点:", found.val)}Delete(&intList, 2)fmt.Print("删除后链表内容: ")Traverse(intList) // 输出: 1 3fmt.Printf("链表长度:%v\n",Len(intList))intList=Reverse(intList)fmt.Print("翻转链表内容: ")Traverse(intList) // 输出: 3 1
}