golang泛型函数与泛型队列使用示例

作者 : admin 本文共9167个字,预计阅读时间需要23分钟 发布时间: 2024-06-5 共1人阅读

1.泛型函数使用

定义一个泛型生成器,功能:取传入的map对象的键的集合并返回

// 生成器(泛型)
// any表示空接口interface{}
// comparable表示一个可比较的接口,实现了该接口的对象可使用==或者!=进行对象比较
// map[K]V 是根据传入的类型生成map对象
// []K 表示返回传入类型的集合
func MapKeys[K comparable, V any](m map[K]V) []K {
	r := make([]K, 0, len(m)) //根据map大小分配[]K内存并返回r
	//遍历map对象m并添加键到集合
	for k := range m {
		r = append(r, k) //添加到集合
	}
	return r //返回集合
}

测试生成器

//1.测试MapKeys函数
	var mmm = map[int]string{1: "2", 2: "4", 4: "8"}
	//map[int]string 相当于MapKeys中的[K comparable, V any],此时K=int,V=string
	//下面执行MapKeys(mmm)后会返回一个整形数组[]int ,
	//因为mmm类型是map[int]string 所以返回[]K相当于返回[]int
	fmt.Println("keys for int:", MapKeys(mmm)) //输入包含map键的集合,键为整数
	//再次测试
	//map[string]int ---> MapKeys中的[K comparable, V any]
	//K ---> string    V ---> int
	//[]K ---> []string
	var mmm1 = map[string]int{"one": 2, "two": 4, "four": 8}
	fmt.Println("keys for string:", MapKeys(mmm1)) //输入包含map键的集合,键为字符串

 测试生成器,直接初始化map并传入

//构造map
	mapStrStr := map[string]string{"zh": "中国", "us": "美国", "jp": "日本"}
	//指定泛型输入类型
	mapstrstrKEY := MapKeys[string, string](mapStrStr)
	fmt.Println("mapStrStr:", mapStrStr, "mapstrsrKey:", mapstrstrKEY)

	//使用泛型函数时直接初始化map
	makeKeysWithInit := MapKeys[int, string](map[int]string{
		1: "中国",
		2: "美国",
		3: "日本",
	})
	fmt.Println("makeKeysWithInit:", makeKeysWithInit)

2.泛型队列使用

泛型队列实现:

// 泛型结构实现
type element[T any] struct {
	next *element[T] //下一元素指针
	val  T           //元素值
}

// 泛型队列实现
type List[T any] struct {
	head, tail *element[T] //队头元素与队尾元素指针
}

// 泛型队列-入队实现
func (lst *List[T]) Push(v T) {
	if lst.tail == nil { //空队
		lst.head = &element[T]{val: v} //队头
		lst.tail = lst.head            //队尾
	} else {
		lst.tail.next = &element[T]{val: v} //向队尾,入队元素
		lst.tail = lst.tail.next            //队尾指向该才入队的元素
	}
}

// 取队列中所有元素,并返回元素列表
func (lst *List[T]) GetAll() []T {
	var elems []T //元素列表
	//遍历队列,从队头到队尾
	for e := lst.head; e != nil; e = e.next {
		elems = append(elems, e.val) //添加到列表
	}
	return elems //返回列表
}

泛型队列测试:

//泛型队列使用
	lst := List[int]{}                 //初始化整数队列
	lst.Push(10)                       //入队
	lst.Push(20)                       //入队
	lst.Push(30)                       //入队
	fmt.Println("list:", lst.GetAll()) //输出队列所有元素

	//泛型队列使用
	lst_str := List[string]{}                      //初始化整数队列
	lst_str.Push("zh")                             //入队
	lst_str.Push("us")                             //入队
	lst_str.Push("jp")                             //入队
	fmt.Println("lst_str list:", lst_str.GetAll()) //输出队列所有元素

泛型队列测试之自定义结构使用

定义结构 

// 定义基础结构
type base struct {
	num int //结构成员
}

在泛型队列中使用结构

//入队自定义结构
	baseQueue := List[base]{} //队列初始化
	for i := range 10 {
		tmp := base{num: (i + 1) * 5} //初始化自定义结构
		baseQueue.Push(tmp)           //入队
	}
	fmt.Println("baseQueue-LIST:", baseQueue.GetAll())

 完整示例:

package main
//导入多个包,一行一个
import (
"fmt"
"maps"
"math"
"strconv"
"time"
"unicode/utf8"
)
// 枚举定义
const (
StateIdle = iota //iota表示未定义整数,默认为:0
StateConnected
StateError
StateRetrying
StateRunning
)
var stateMap = map[int]string{
StateIdle:      "Idle",
StateConnected: "Connected",
StateError:     "Error",
StateRetrying:  "Retrying",
StateRunning:   "Running",
}
// geometry : 定义接口
type geometry interface {
area() float64  //函数名  返回类型
perim() float64 //函数名  返回类型
}
// 定义结构area
type rect struct {
width, height float64 //同类成员写一行,逗号隔开 / 成员名 类型
}
// 定义结构circle
type circle struct {
radius float64 //成员名 类型
}
// area() : 实现接口方法area
func (a rect) area() float64 {
return a.width * a.height
}
// perim :实现接口方法perim
// func (参数名 类型) 函数名() 返回类型
func (a rect) perim() float64 {
return 2*a.width + 2*a.height
}
func (c circle) area() float64 {
return math.Pi * c.radius * c.radius
}
func (c circle) perim() float64 {
return 2 * math.Pi * c.radius
}
// 封装接口调用方法
// func 函数名(参数名 类型)
func callInterfaceGeometry(g geometry) {
fmt.Println(g)
fmt.Println("area:", g.area())
fmt.Println("perim:", g.perim())
}
// 同类开多个参数默认写法
func add2(a int, b int) int {
return a + b
}
// 同类开多个参数简洁写法
func add3(a, b, c int) int {
return a + b + c
}
// 多个返回值写法
func add(a int, b int) (int, int) {
return a * 5, b * 5
}
// 多个返回值写法
func abc(a int, b int) (int, int, int) {
return a, b, a + b
}
// 可变参数写法
func sum(nums ...int) int {
total := 0
for _, v := range nums {
total += v
}
fmt.Println("计算结果:", total)
return total
}
// 闭包函数使用
func myFunc() func() int {
i := 0
return func() int {
i++
print(i)
return i
}
}
// 递归相乘
func fib(n int) int {
if n == 0 {
return 1
}
return n * fib(n-1)
}
// 递归前两个数相加
func fib1(n int) int {
if n  ", "key:", k, "value:", v)
}
stringMap := make(map[string]string)
stringArr := []string{"中国", "美国", "日本"}
stringArr1 := []string{"ZH", "US", "JP"}
for i, v := range stringArr1 {
stringMap[v] = stringArr[i]
}
for k, v := range stringMap {
fmt.Println(k, v)
}
sum(1, 2, 3, 4, 5, 6, 7, 8, 9)
fv := myFunc() //调用闭包函数,返回函数
fv()           //调用返回的函数
fmt.Println("递归函数调用-相乘:", fib(5))
fmt.Println("递归函数调用-相加:", fib1(5))
//变量声明与使用
var x1 = 123
x2 := 456
fmt.Println(x1, x2)
var v1, v2, v3 = 2017, 2019, 2022
fmt.Println(v1, v2, v3)
v4, v5, v6 := "VS2017", "VS2019", "VS2022"
fmt.Println(v4, v5, v6)
//常量声明与使用
const YEAR, MONTH, WEEK = 12, 30, 7
print("
", YEAR, MONTH, WEEK, "
")
//循环使用
fmt.Println(">>>>>>>>外部变量循环>>>>>>>>>>>>>")
i := 10
for i >>>>>>>常规循环>>>>>>>>>>>>>")
for j := 0; j  15 {
fmt.Println("a>15", a)
} else if a > 12 {
fmt.Println("a>12,a<15", a)
} else {
fmt.Println("a= 30 {
fmt.Println("准备下班...")
}
break
default:
fmt.Println("工作中...")
break
}
//函数在表达式中使用
typeChk := func(i interface{}) {
switch t := i.(type) {
case bool:
fmt.Println("bool:", t)
case int:
fmt.Println("int:", t)
default:
fmt.Println("not a type:", t)
}
}
typeChk(255)
typeChk(!false)
typeChk(m)
//声明数组不初始化
var arr1 [5]int
//初始化数组
arr1[0] = 100
//取数组元素
arr1_elm_0 := arr1[0]
fmt.Println(arr1_elm_0)
//声明数组并直接初始化
arr2 := [5]int{1, 2, 3, 4, 5}
fmt.Println(arr2)
//声明可变长数组并初始化,数组大由初始化的元素个数决定
arr3 := [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9}
fmt.Println(arr3, len(arr3))
for k, v := range arr3 {
fmt.Println(k, v)
}
//声明可变数组,长度由初始化值决定
b := [...]int{100, 3: 400, 500, 9: 1000} //指定第3个元素值为400
fmt.Println("idx:", b)
for i, v := range b {
fmt.Println("===>指定元素索引:", i, v)
}
//二维数组声明
var arr2d [2][3]int
//二维数组初始化
for i := 0; i < 2; i++ {
for j := 0; j < 3; j++ {
arr2d[i][j] = i + j + 1
}
}
//遍历二维数组
for i := 0; i < 2; i++ {
for j := 0; j 输出二维数组元素值:[", i, j, "]", arr2d[i][j])
}
}
//声明二维数组直接初始化
arr2d_new := [2][3]int{
{1, 2, 3},
{4, 5, 6},
}
//遍历二维数组
for i := 0; i < 2; i++ {
for j := 0; j 输出二维数组元素值:[", i, j, "]", arr2d_new[i][j])
}
}
//字符串数组使用,也叫分片(Slices)
var s1 []string
fmt.Println("for s1:", s1, len(s1), cap(s1), s1 == nil, len(s1) == 0)
if s1 == nil {
fmt.Println("空字符串数组(Slices)")
}
if len(s1) == 0 {
fmt.Println("字符串数组(Slices)的大小为0")
}
//使用make为Slice分配内存
s2 := make([]string, 3)
fmt.Println("for s2:", s2, len(s2), cap(s2), s2 == nil, len(s2) == 0)
//赋值Slice
for i := 0; i  value of Slices : ", v)
}
//使用append向Slice中添加5个元素
for i := 0; i  ", k, v)
}
//复制Slices副本
s2_copy := make([]string, len(s2)) //根据s2大小分配新内存
copy(s2_copy, s2)                  //复制s2到s2_copy
fmt.Println(s2_copy)
//遍历s2_copy
for k, v := range s2_copy {
fmt.Println("k,v in s2_copy: ===> ", k, v)
}
newSlice := s2[2:5] //取索引为2开始到索引为5结结束的所有元素并返回新Slices
fmt.Println("取索引为2开始到索引为5结束的所有元素并返回新Slices:", newSlice)
from2toend := s2[2:] //取索引为2开始,所有元素
fmt.Println("取索引为2开始,所有元素:", from2toend)
from0to5 := s2[:5] //取索引为0开始,索引为5结束的所有元素并返回新Slices
fmt.Println("取索引为0开始,索引为5结束的所有元素并返回新Slices", from0to5)
//使用make为二维数组分配内存
new2darr := make([][]int, 5)
for i := 0; i < 5; i++ {
innerLen := i + 1
new2darr[i] = make([]int, innerLen) //动态创建数组
for j := 0; j map1 顺序输出:", k, v)
}
for k, v := range map2 {
fmt.Println("===>map2 乱序输出:", k, v)
}
map3 := map[string]string{"zh": "中国", "us": "美国", "jp": "日本"}
for k, v := range map3 {
fmt.Println(k, v)
}
val1 := 999
fmt.Println("变量val1原始值:", val1)
fmt.Println("变量val1原始地址:", &val1)           //输出变量地址
byVal(val1)                                 //传入变量 ,因为变量在外部,所以值 没有被改变 些时val1值还是999
fmt.Println("byVal函数初始化后,val1值:", val1)     //输出999
byPointer(&val1)                            //传入变量地址后,会将地址址初始化为0,些时val1值为0
fmt.Println("变量val1原始地址:", &val1)           //输出变量地址
fmt.Println("byPointer函数初始化后,val1值:", val1) //输出0
//字符串编码使用
const sss = "สวัสดี"
fmt.Println("Len:", len(sss))
for i := 0; i < len(sss); i++ {
fmt.Printf("%x ", sss[i])
}
fmt.Println()
fmt.Println("Rune count:", utf8.RuneCountInString(sss))
for idx, runeValue := range sss {
fmt.Printf("%#U starts at %d
", runeValue, idx)
}
fmt.Println("
Using DecodeRuneInString")
for i, w := 0, 0; i < len(sss); i += w {
runeValue, width := utf8.DecodeRuneInString(sss[i:])
fmt.Printf("%#U starts at %d
", runeValue, i)
w = width
examineRune(runeValue)
}
str := "Hello, 世界"
fmt.Println("bytes =", len(str))
fmt.Println("runes =", utf8.RuneCountInString(str))
mystr := "你好,中国"
fmt.Println("bytes =", len(mystr))
for i := 0; i  FrameCount:", vf.FrameCount())
fmt.Println("===>VideoFrame:", vf.getVideoFrame())
//使用结构方法
fmt.Println("===>VideoFrame->ID:", vf.Id())
vf.SetId(8888)
fmt.Println("===>VideoFrame-ID:", vf.Id())
//使用结构base与container
cb := container{ //初始化结构container
base: base{ //初始化结构base
num: 888, //base结构成员num
},
str: "Hello Container", //container结构成员str
}
fmt.Println("结构Container:", cb)
fmt.Printf("结构Container对象cb={container->base->num: %v, container->str: %v}
", cb.num, cb.str)
fmt.Println("结构container内嵌结构base的num成员:", cb.base.num)
fmt.Println("结构base的成员方法describe:container->base->describe()", cb.describe())
//临时定义接口
type describer interface {
describe() string //跳到base结构的describe方法
}
fmt.Println("--->describe:", cb.describe()) //调用内嵌结构的describe方法
cb.SetNum(999)
var d describer = cb                        //调用base结构的SetNum
fmt.Println("===>describer:", d.describe()) //调用接口describer,接口再转到base结构对接口的实现describe方法
//泛型队形测试
//1.测试MapKeys函数
var mmm = map[int]string{1: "2", 2: "4", 4: "8"}
//map[int]string 相当于MapKeys中的[K comparable, V any],此时K=int,V=string
//下面执行MapKeys(mmm)后会返回一个整形数组[]int ,
//因为mmm类型是map[int]string 所以返回[]K相当于返回[]int
fmt.Println("keys for int:", MapKeys(mmm)) //输入包含map键的集合,键为整数
//再次测试
//map[string]int ---> MapKeys中的[K comparable, V any]
//K ---> string    V ---> int
//[]K ---> []string
var mmm1 = map[string]int{"one": 2, "two": 4, "four": 8}
fmt.Println("keys for string:", MapKeys(mmm1)) //输入包含map键的集合,键为字符串
//构造map
mapStrStr := map[string]string{"zh": "中国", "us": "美国", "jp": "日本"}
//指定泛型输入类型
mapstrstrKEY := MapKeys[string, string](mapStrStr)
fmt.Println("mapStrStr:", mapStrStr, "mapstrsrKey:", mapstrstrKEY)
//使用泛型函数时直接初始化map
makeKeysWithInit := MapKeys[int, string](map[int]string{
1: "中国",
2: "美国",
3: "日本",
})
fmt.Println("makeKeysWithInit:", makeKeysWithInit)
//泛型队列使用
lst := List[int]{}                 //初始化整数队列
lst.Push(10)                       //入队
lst.Push(20)                       //入队
lst.Push(30)                       //入队
fmt.Println("list:", lst.GetAll()) //输出队列所有元素
//泛型队列使用
lst_str := List[string]{}                      //初始化整数队列
lst_str.Push("zh")                             //入队
lst_str.Push("us")                             //入队
lst_str.Push("jp")                             //入队
fmt.Println("lst_str list:", lst_str.GetAll()) //输出队列所有元素
//入队自定义结构
baseQueue := List[base]{} //队列初始化
for i := range 10 {
tmp := base{num: (i + 1) * 5} //初始化自定义结构
baseQueue.Push(tmp)           //入队
}
fmt.Println("baseQueue-LIST:", baseQueue.GetAll())
}

本站无任何商业行为
个人在线分享 » golang泛型函数与泛型队列使用示例
E-->