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
}
相关推荐
kkkAloha15 小时前
JS笔记汇总
开发语言·javascript·笔记
LawrenceLan21 小时前
Flutter 零基础入门(十一):空安全(Null Safety)基础
开发语言·flutter·dart
txinyu的博客1 天前
解析业务层的key冲突问题
开发语言·c++·分布式
码不停蹄Zzz1 天前
C语言第1章
c语言·开发语言
猫头虎1 天前
如何在浏览器里体验 Windows在线模拟器:2026最新在线windows模拟器资源合集与技术揭秘
运维·网络·windows·系统架构·开源·运维开发·开源软件
行者961 天前
Flutter跨平台开发在OpenHarmony上的评分组件实现与优化
开发语言·flutter·harmonyos·鸿蒙
阿蒙Amon1 天前
C#每日面试题-Array和ArrayList的区别
java·开发语言·c#
SmartRadio1 天前
ESP32添加修改蓝牙名称和获取蓝牙连接状态的AT命令-完整UART BLE服务功能后的完整`main.c`代码
c语言·开发语言·c++·esp32·ble
且去填词1 天前
Go 语言的“反叛”——为什么少即是多?
开发语言·后端·面试·go
知乎的哥廷根数学学派1 天前
基于生成对抗U-Net混合架构的隧道衬砌缺陷地质雷达数据智能反演与成像方法(以模拟信号为例,Pytorch)
开发语言·人工智能·pytorch·python·深度学习·机器学习