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

练习 泛型类型

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

  • 用全局函数 Add 和 Delete,传递双指针 **List[T],避免方法接收者语法问题。
  • 给 T 加 comparable 约束,保证可以用 ==。
  • 其他方法(如 Find、Traverse)仍然用方法接收者 *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
}
相关推荐
nice_lcj5202 小时前
ThreadLocal 入门:它是怎么隔离数据的、为什么会导致内存泄漏
java·开发语言·后端·面试·并发编程·内存泄漏·threadlocal
百事牛科技2 小时前
Excel的三种密码:防看、防存、防乱改,各管各的
windows·excel
紧跟先前的步伐2 小时前
Go AI Agent 实战 28|Agent 的预算、超时与停止条件
开发语言·人工智能·后端·ai·golang
bksczm3 小时前
InnoDB 行格式详解:DYNAMIC / COMPACT / COMPRESSED / REDUNDANT
java·开发语言·数据库
春涧草茶3 小时前
慢就是快16-1协程
开发语言·前端·python
Dovis(誓平步青云)4 小时前
启元 T1 Pro 人机相声搭档:语音-触摸双通道的启元机器人节奏引擎设计
开发语言·前端·javascript·microsoft·交互
做科研的周师兄4 小时前
【R语言实战】MixSIAR 氢氧同位素水源解析全流程:从混合空间校验到贝叶斯 MCMC 收敛诊断(后附完整代码)
java·大数据·开发语言
.痞老板.5 小时前
java ee--计算机是如何工作的
java·开发语言·java-ee
奇树谦5 小时前
Qt Quick 图片加载与 GPU 纹理机制详解:QImage、QQuickTextureFactory、QSGTexture 与异步加载
开发语言·qt·系统架构
青梅味猪大肠5 小时前
【操作系统-60】临近适应算法
java·linux·开发语言·嵌入式硬件·算法·操作系统