go tour泛型

5 泛型

类型参数

  • s 是满足内置约束 comparable 的任何类型 T 的切片。 x 也是相同类型的值。
  • comparable 是一个有用的约束,它能让我们对任意满足该类型的值使用 ==!= 运算符。
go 复制代码
func Index[T comparable](s []T, x T) int
go 复制代码
// 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

练习 泛型类型

作为练习,请为此链表的实现添加一些功能。

  • 用全局函数 AddDelete,传递双指针 **List[T],避免方法接收者语法问题。
  • Tcomparable 约束,保证可以用 ==
  • 其他方法(如 FindTraverse)仍然用方法接收者 *List[T],这样 intList.Traverse() 能正常调用。
  • 无比较使用T any。有比较操作使用T comparabel
go 复制代码
package main

import "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 := *l
		for 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).next
		return
	}
	current := *l
	for 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 := l
	for current != nil {
		if current.val == value {
			return current
		}
		current = current.next
	}
	return nil
}

// Traverse 遍历链表并打印每个节点的值
func Traverse[T any](l *List[T]) {
	current := l
	for current != nil {
		fmt.Print(current.val, " ")
		current = current.next
	}
	fmt.Println()
}

//链表长度
func Len[T any](l *List[T]) int {
	current := l
	count:=0
	for current != nil {
		count++
		current = current.next
	}
	return count
}

func Reverse[T any](l *List[T]) *List[T] {
    var newHead *List[T] = nil
    current := l
    for current != nil {
        next := current.next
        current.next = newHead
        newHead = current
        current = 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 3

	found := Find(intList, 2)
	if found != nil {
		fmt.Println("找到节点:", found.val)
	}

	Delete(&intList, 2)
	fmt.Print("删除后链表内容: ")
	Traverse(intList) // 输出: 1 3
	
	fmt.Printf("链表长度:%v\n",Len(intList))
	
	
	
	intList=Reverse(intList)
	fmt.Print("翻转链表内容: ")
	Traverse(intList) // 输出: 3 1
}
相关推荐
菥菥爱嘻嘻2 小时前
JS手写代码篇---Pomise.race
开发语言·前端·javascript
南瓜胖胖2 小时前
【R语言编程绘图-调色】
开发语言·r语言
码农捻旧3 小时前
MySQL 9.3 超详细下载安装教程(Windows版)附图文说明
数据库·windows·mysql·adb·程序员创富
lanbing3 小时前
非常适合初学者的Golang教程
开发语言·后端·golang
stormsha4 小时前
GO语言进阶:掌握进程OS操作与高效编码数据转换
开发语言·数据库·后端·golang·go语言·源代码管理
老神在在0015 小时前
javaEE1
java·开发语言·学习·java-ee
魔道不误砍柴功5 小时前
《接口和抽象类到底怎么选?设计原则与经典误区解析》
java·开发语言
我是李武涯6 小时前
C++ 条件变量虚假唤醒问题的解决
开发语言·c++·算法
编码小笨猪7 小时前
[ Qt ] | 常用控件(三):
开发语言·qt
Bioinfo Guy7 小时前
R包安装报错解决案例系列|R包使用及ARM架构解决data.table安装错误问题
开发语言·arm开发·r语言