golang学习笔记--泛型编程

目录

【1】泛型写法

【2】自定义泛型

【3】内置泛型类型约束

【4】泛型函数

【5】泛型切片、集合、通道

【6】泛型接口

【7】泛型结构体


golang 1.18版本后支持泛型编程。

# 什么是泛型

1. 泛型即开发过程中编写适用于所有类型的模板,只有在具体使用的时候才能确定其真正的类型

# 泛型的作用与应用场景

1. 增加代码的复用,从同类型的复用到不同类型的代码复用

2. 应用于不同类型间代码复用的场景,即不同类型需要写相同的处理逻辑时,最适合用泛型

# 泛型的利弊

1. 提高了代码复用率,提高了编程效率

2. 不同类型间代码复用,使得代码风格更加优雅

3. 增加了编译器的负担,降低了编译效率

# golang的泛型怎么使用

1. 泛型函数

2. 泛型类型

3. 泛型接口

4. 泛型结构体

5. 泛型receiver

# 泛型限制

1. 匿名结构体与匿名函数不支持泛型

2. 不支持类型断言

3. 不支持泛型方法,只能通过receiver来实现方法的泛型处理

4. ~后的类型必须为基本类型,不能为接口类型

【1】泛型写法

func SimpleCase() {
	var a, b = 3, 4
	var c, d float64 = 5.4, 6.3
	fmt.Println("不使用泛型,数字比较:", getMaxNumInt(a, b))
	fmt.Println("不使用泛型,数字比较:", getMaxNumFloat(c, d))

	//由编译器推断输入的类型
	fmt.Println("使用泛型,数字比较:", getMaxNum(a, b))
	//显示指定传入的类型
	fmt.Println("使用泛型,数字比较:", getMaxNum[float64](c, d))
}

func getMaxNumInt(a, b int) int {
	if a > b {
		return a
	}
	return b
}

func getMaxNumFloat(a, b float64) float64 {
	if a > b {
		return a
	}
	return b
}

//泛型函数定义,可以使用interface{}包裹防止加 * 时被当做乘法运算,也可以不包裹
func getMaxNum[T interface{ int | float64 }](a, b T) T {
	if a > b {
		return a
	}
	return b
}

【2】自定义泛型


type CusNumT interface {
	// 支持 uint8 、int32 、 float64 与 int64及其衍生类型
	// ~ 标识支持类型的衍生类型
	// | 表示取并集
	// 多行之间取交集
	uint8 | int32 | float64 | ~int64
	int32 | float64 | ~int64 | uint16
}

// MyInt64 为int64的衍生类型,具有基础类型int64的新类型,与int64是不同类型
type MyInt64 int64

// MyInt32 为 int32 的别名,与 int32 是同一类型
type MyInt32 = int32

func CusNumTCase() {
	var a, b int32 = 3, 4
	var a1, b1 MyInt32 = a, b
	fmt.Println("自定义泛型,数字比较:", GetMaxCusNum(a, b))
	fmt.Println("自定义泛型,数字比较:", GetMaxCusNum(a1, b1))

	var c, d float64 = 5.4, 6.3

	fmt.Println("自定义泛型,数字比较:", GetMaxCusNum(c, d))

	var e, f int64 = 7, 8
	var g, h MyInt64 = 7, 8

	fmt.Println("自定义泛型,数字比较:", GetMaxCusNum(e, f))
	fmt.Println("自定义泛型,数字比较:", GetMaxCusNum(g, h))
}

func GetMaxCusNum[T CusNumT](a, b T) T {
	if a > b {
		return a
	}
	return b
}

【3】内置泛型类型约束

//内置类型
func BuiltInCase() {
	var a, b string = "abc", "efg"
	fmt.Println("内置 comparable 泛型类型约束", getBuiltInComparable[string](a, b))

	var c, d float64 = 100, 100
	fmt.Println("内置 comparable 泛型类型约束", getBuiltInComparable(c, d))

	var e = 100.123
	var f = "你好"
	printBuiltInAny(e)
	printBuiltInAny(f)
}

func getBuiltInComparable[T comparable](a, b T) bool {
	//comparable 类型,只支持 ==  !=  两个操作
	return a == b
}

func printBuiltInAny[T any](a T) {
	fmt.Println("内置 any 泛型类型约束", a)
}

【4】泛型函数

package _case

import "fmt"

type user struct {
	ID   int64
	Name string
	Age  uint8
}

type address struct {
	ID             int
	Province, City string
}

// 集合转列表
func mapToList[K comparable, T any](mp map[K]T) []T {
	list := make([]T, len(mp))
	var i int

	for _, data := range mp {
		list[i] = data
		i++
	}
	return list
}

func myPrintln[T any](ch chan T) {
	for data := range ch {
		fmt.Println(data)
	}
}

func TTypeCase() {
	userMp := make(map[int64]user, 0)
	userMp[1] = user{1, "tom", 19}
	userMp[2] = user{2, "jack", 20}
	userList := mapToList[int64, user](userMp)
	ch := make(chan user)
	go myPrintln(ch)
	for _, u := range userList {
		ch <- u
	}

	addrMp := make(map[int64]address, 0)
	addrMp[1] = address{1, "上海", "浦东"}
	addrMp[2] = address{2, "上海", "闵行"}
	addrList := mapToList[int64, address](addrMp)
	ch1 := make(chan address)
	go myPrintln(ch1)
	for _, u := range addrList {
		ch1 <- u
	}
}

调用

package main

import (
	"context"
	"fmt"
	"os"
	"os/signal"
	_case "project01/generic-T/case"
)

func main() {
	_case.TTypeCase()
	ctx, stop := signal.NotifyContext(context.Background(), os.Interrupt, os.Kill)
	defer stop()
	<-ctx.Done()
}

【5】泛型切片、集合、通道

// 泛型切片的定义
type List[T any] []T

// 泛型集合的定义
// 声明两个泛型 分别为K , V
type MapT[K comparable, V any] map[K]V

// 泛型通道的定义
type Chan[T any] chan T

func TTypeCase1() {
	userMp := make(MapT[int64, user], 0)
	userMp[1] = user{1, "tom", 19}
	userMp[2] = user{2, "jack", 20}

	var userList List[user]
	userList = mapToList[int64, user](userMp)

	ch := make(Chan[user])
	go myPrintln(ch)
	for _, u := range userList {
		ch <- u
	}

	addrMp := make(MapT[int, address], 0)
	addrMp[1] = address{1, "上海", "浦东"}
	addrMp[2] = address{2, "上海", "闵行"}

	var addrList List[address]
	addrList = mapToList(addrMp)
	ch1 := make(Chan[address])
	go myPrintln(ch1)
	for _, u := range addrList {
		ch1 <- u
	}
}

【6】泛型接口

package _case

import (
	"fmt"
)

// 基本接口,可用于变量的定义
type ToString interface {
	String() string
}

func (u user) String() string {
	return fmt.Sprintf("ID:%d,Name:%s,Age:%d", u.ID, u.Name, u.Age)
}

func (addr address) String() string {
	return fmt.Sprintf("ID:%d,Province:%s,City:%s", addr.ID, addr.Province, addr.City)
}

// 泛型接口
type GetKey[T comparable] interface {
	any
	Get() T
}

func (u user) Get() int64 {
	return u.ID
}
func (addr address) Get() int {
	return addr.ID
}

// 列表转集合
func listToMap[K comparable, T GetKey[K]](list []T) map[K]T {
	mp := make(MapT[K, T], len(list))
	for _, data := range list {
		mp[data.Get()] = data
	}
	return mp
}

func InterfaceCase() {
	userList := []GetKey[int64]{
		user{1, "tom", 18},
		user{2, "jack", 20},
	}
	addrList := []GetKey[int]{
		address{1, "上海", "陆家嘴"},
		address{2, "上海", "虹桥"},
	}
	userMp := listToMap[int64, GetKey[int64]](userList)
	fmt.Println(userMp)

	addrMp := listToMap[int, GetKey[int]](addrList)
	fmt.Println(addrMp)
}

【7】泛型结构体

package _case

import "fmt"

//泛型结构体
type MyStruct[T interface{ *int | *string }] struct {
	Name string
	Data T
}

func (m MyStruct[T]) GetData() T {
	return m.Data
}

func ReceiverCase() {
	data := 18
	myStruct := MyStruct[*int]{
		Name: "lucy",
		Data: &data,
	}
	data1 := myStruct.GetData()
	fmt.Println(*data1)

	str := "hello"
	myStruct1 := MyStruct[*string]{
		Name: "lucy",
		Data: &str,
	}
	str1 := myStruct1.GetData()
	fmt.Println(*str1)

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值