day16 泛型

了解泛型

  • 1.18后引入泛型(类型参数)
  • 用户传入参数类型
  • 场景使用很少
  • 1.18以前使用 [反射] 来处理不同参数类型的问题
  • 泛型也是使用 [] 和数组很像! 即:[T any]泛型的约束
  • 泛型的作用:减少代码重复型,只针对不同类型相同功能的代码
  • 泛型的类型:多个类型(类型不确定)
  • 把静态语言 转换成 动态语言

泛型的类型

  • T 就是一个占位符。 类型的形式参数,T是不确定的,需要在使用时传递类型
  • 由于T的类型是不确定的,需要增加一下约束 int|float32|float64|string
package main

import "fmt"

type s1 []int

// Slice 定义泛型切片类型, 类型参数化
/*
	- T 就是一个占位符。 类型的形式参数,T是不确定的,需要在使用时传递类型
	- 由于T的类型是不确定的,需要增加一下约束 int|float32|float64|string
*/
type Slice[T int | float64] []T

func main() {
	/* 泛型的类型 */
	var a s1 = []int{1, 2, 3}
	fmt.Println(a)

	// 使用泛型创建变量。 泛型就是将数据语言有静态变为动态类型
	var b Slice[int] = []int{1, 2, 3}
	fmt.Printf("%T\n", b) // main.Slice[int]
	var c Slice[float64] = []float64{1.1, 2.2, 3.3}
	fmt.Printf("%T\n", c) // main.Slice[float64]
	fmt.Println("泛型:", b, c)
}

泛型使用

  • 泛型的参数类型的属性。不止一个,所有东西都可以泛型化
package main

import "fmt"

type MyStruct[T int | string] struct {
	id   T // 多类型
	Name string
	sex  bool
}
type MyInterface[T string | int | float64] interface {
	Print1(data string)
	Print2(data T)
}
type MyChan[T string | int] chan T

func main() {
	/* T 泛型的参数类型的属性。不止一个,所有东西都可以泛型化 */

	// 1. 泛型化 map  GenericsMap[T,T]
	type GenericsMap[K string | int | float64, V string | int | float64] map[K]V

	// 1.1 实例化泛型 map
	var score1 GenericsMap[string, int] = map[string]int{
		"a": 100,
		"b": 200,
		"c": 300,
	}
	fmt.Printf("score1=%v\n", score1)

	var score2 GenericsMap[int, int] = map[int]int{
		1: 100,
		2: 200,
		3: 300,
	}
	fmt.Printf("score2=%v\n", score2)

	// 2. 泛型化 slice genericsSlice[T]
	type genericsSlice[T string | int | float64 | float32] []T

	// 3. 结构体 泛型 MyStruct
	var genericsStruct1 MyStruct[int] = MyStruct[int]{10, "张三", true}
	fmt.Printf("genericsStruct1=%v\n", genericsStruct1)
	var genericsStruct2 MyStruct[string] = MyStruct[string]{"我不是", "张三", true}
	fmt.Printf("genericsStruct2=%v\n", genericsStruct2)

	// 4. 接口泛型
	//MyInterface()

	// 5. 通道
	//MyChan

}

特殊的泛型

package main

import "fmt"

func main() {
	/* 特殊的泛型:一般不会使用*/

	type MyGenericsInt[T string | int] = int // 结果一定是整型
	var a1 MyGenericsInt[string] = 1
	var b1 MyGenericsInt[int] = 2
	fmt.Println(a1, b1)
	//var c1 MyGenericsInt[string] = "1234" // 因为底层类型设定的是 int。 传入泛型的类型任意,但是结果必须是int,即:赋值时结果是整型
}

泛型函数

package main

import "fmt"

// MySumSlice 定义泛型类型
type MySumSlice[T string | int | float64 | float32] []T

// MySumSlice 函数调用者泛型化
func (s MySumSlice[T]) sum(s1 int) T {
	fmt.Printf("Sum s1: %d\n", s1)
	var sum T
	for _, v := range s {
		sum += v
	}
	return sum
}

// Add 参数泛型化
func Add[T string | int | float64 | float32](a T, b T) T {
	return a + b
}
func main() {
	/*
		泛型函数
			- 1 调用者不同,传入泛型类型。
			- 2.普通函数,即:参数泛型化
	*/

	// 1. 调用者不同。 引入泛型化的数据类型调用函数
	var intSlice MySumSlice[int] = []int{1, 2, 3, 4, 5}
	intRes := intSlice.sum(1235456)
	fmt.Println("intRes:", intRes)
	var float32Slice MySumSlice[float32] = []float32{1.2, 2.2, 3, 4, 5}
	float32Res := float32Slice.sum(222)
	fmt.Println("float32Res:", float32Res)

	// 2. 函数参数泛型化,同类型参数支持自动推到 ADD(int,int)
	var ia int = 1
	var ib int = 1
	addRes1 := Add[int](ia, ib)
	fmt.Println("addRes1:", addRes1)
	var fa float32 = 12.33
	var fb float32 = 1.235 // 遵循四舍五入
	addRes2 := Add[float32](fa, fb)
	fmt.Println("addRes2:", addRes2)
	var sa string = "abc"
	var sb string = "xyz"
	addRes3 := Add[string](sa, sb)
	fmt.Println("addRes3:", addRes3)

}

自定义泛型

package main

import "fmt"

type genericsInterface interface {
	string | int | float64 | float32 | int8 | int16 | int32
}

func getMax[T genericsInterface](a, b T) T {
	if a > b {
		return a
	}
	return b
}

func main() {
	/* 自定义泛型 */
	var a = 10
	var b = 20
	fmt.Println(getMax(a, b))
	var c = "10"
	var d = "20"
	fmt.Println(getMax(c, d))
}

内置泛型

package main

import "fmt"

// int8 衍生类型
type int8AT int8 // int8AT 就是 int8 的衍生类型
type int8BT int8 // intB 就是 int8 的衍生类型

// MyGenerics01 自定义 泛型类型 接口. ~表示可以匹配该类型的衍生类型
type MyGenerics01 interface {
	~int8
}

func compareTheSize[T MyGenerics01](a, b T) T {
	if a > b {
		return a
	}
	return b
}

func main() {
	/*
		内置泛型
			- any  就是一个泛型,内置类型。interface{}
			- comparable 表示比较所有的类型
			- 新符号 (~)衍生类型
	*/

	// ~ 新符号使用
	var a1 int8AT = 3
	var b1 int8AT = 5
	fmt.Println(a1, b1)
	fmt.Printf("%T\n", a1) // main.int8AT
	fmt.Printf("%T\n", b1) // main.int8BT
	//fmt.Println(compareTheSize(a1, b1))
	fmt.Println(compareTheSize(b1, a1))
}

posted @ 2024-07-03 01:34  染指未来  阅读(3)  评论(0编辑  收藏  举报