【Golang】合理运用泛型,简化开发流程
✨✨ 欢迎大家来到景天科技苑✨✨
🎈🎈 养成好习惯,先赞后看哦~🎈🎈
🏆 作者简介:景天科技苑
🏆《头衔》:大厂架构师,华为云开发者社区专家博主,阿里云开发者社区专家博主,CSDN全栈领域优质创作者,掘金优秀博主,51CTO博客专家等。
🏆《博客》:Python全栈,Golang开发,PyQt5和Tkinter桌面开发,小程序开发,人工智能,js逆向,App逆向,网络系统安全,数据分析,Django,fastapi,flask等框架,云原生K8S,linux,shell脚本等实操经验,网站搭建,数据库等分享。所属的专栏:Go语言开发零基础到高阶实战
景天的主页:景天科技苑
Go语言中的泛型
一、泛型介绍
Go语言自1.18版本开始引入了泛型支持,这一特性极大地增强了代码的灵活性和重用性。
泛型通过引入类型参数,使得函数、类型和方法能够处理多种数据类型,从而减少了重复代码,提高了开发效率。本文将详细介绍Go语言中泛型的用法,并通过实际案例展示泛型在编程中的具体应用。
泛型:多种不确定的类型
在泛型之前,我们定义一个变量或函数参数类型,类型都是写死的,比如:
var name string
func test(name string){}
这样,功能就比较受限。
如果我们想要编写一个反转切片的函数,需要为每种类型分别编写一个函数。例如,反转整型切片和反转浮点型切片的函数需要分别实现。但是,从Go 1.18开始,我们可以使用泛型来实现一个通用的反转函数。
我们先用空接口来测试多种类型的适配实现,还是需要做类型判断
package mainimport "fmt"func main() {str := []string{"1", "2", "3", "4", "5"}printSlice(str)str2 := []int{1, 2, 3, 4, 5}printSlice(str2)}func printSlice(i interface{}) {// 断言 x.(T), 如果x实现了T,那么就将 x转换为T类型//这样的话,也是需要做好多种判断switch i.(type) {case []string:for _, i3 := range i.([]string) {fmt.Println(i3)}fmt.Println()case []int:for _, i3 := range i.([]int) {fmt.Println(i3)}}// 其他很多种类型都要做判断,所以通过这种方式不现实.........}
这种情况,传递的参数进来,需要自己做N种判断来进行适配。
也可以通过反射来实现,在go1.18之后,我们最常用的还是泛型
泛型的作用:
1、减少重复性的代码,提高安全性
- 针对不同的类型,写了相同逻辑的代码,我们就可以通过泛型来简化代码!
2、在1.18版本之前 反射 来实现。 泛型并不能完全取代反射!
二、泛型的基本概念
不限定参数的类型,让调用的人自己去定义类型。
类型参数:类型参数是在函数或类型定义时,紧随名称后的方括号中定义的。例如,func T any {…}中的[T any]表示类型参数T可以是任何类型。
约束:约束是指类型参数必须满足的接口。例如,any是一个内置约束,表示任何类型。通过约束,可以限制类型参数的范围,确保它们具备某些特定的行为或属性。
三、泛型类型的声明和使用
1. 声明泛型类型:使用[]括起方括号来声明泛型类型。例如:
type List[T any] []T
这里,List[T any]表示一个泛型类型,其中T是类型参数,可以是任何类型。any是约束, 是Go语言中的空接口,表示 T 可以是任何类型。
T 说白了就是一个占位符,类型的形式参数,T是不确定的,需要在使用的时候进行传递。也可以随便用个其他字母代替
2. 使用泛型类型:在使用泛型类型时,需要指定类型参数。
T是占位符,在使用的时候,必须要实例化为具体的类型。
声明泛型类型后,可以像普通类型一样使用它。例如:
myIntList := List[int]{1, 2, 3}
这里,myIntList是一个整型列表。
3. 泛型类型的应用:泛型类型可以应用于结构体、接口、函数和方法中。
例如,定义一个泛型结构体:
type Box[T any] struct { content T
} func (b Box[T]) Content() T { return b.content
}
使用:
box := Box[int]{content: 123}
fmt.Println(box.Content()) // 输出: 123
泛型使用案例1:
普通的定义类型,这个类型只能代表本身一个,泛型类型,我们可以实现,参数类型传递
package mainimport "fmt"// 我们定义的结构都是一样的,只是它的类型不同,就需要重新定义这么多的类型。
// 思考:是否有一种机制,只定义一个类型就可以代表上面的所有类型?
// 泛型:类型 参数化了! 参数:人为传递的/*
1、T 说白了就是一个占位符,类型的形式参数,T是不确定的,需要在使用的时候进行传递。
2、由于T类型是不确定的,我们需要加一些约束 int|float64|float32 。告诉编译器我这个T,只接受int、float64、float32 类型
3、我们这里定义的类型是什么?Slice[T]
*/// Slice 这种类型的定义方式,带了类型形参,和普通定义类型就完全不同的。
// 普通的定义类型,这个类型只能代表本身一个,泛型类型,我们可以实现,参数类型传递。
// 我们可以在使用的时候来定义类型。
// 语法糖:简化开发
// T后面是约束,约束用户只能用哪些类型
// 创建个不固定类型的切片类型Slice
type Slice[T int | float64 | float32] []Tfunc main() {//使用的时候,必须要实例化为具体的类型// Slice是我们上面自己定义的类型,中括号里面是约束,在使用时要用具体的类型var a Slice[int] = []int{1, 2, 3}fmt.Printf("%T\n", a) // Slice[int]var b Slice[float64] = []float64{1.0, 2.0, 3.0}fmt.Printf("%T\n", b) // Slice[float64]// 不能够赋值(string 不在T的约束当中,不能实例化的)//var c Slice[string] = []string{"jigntian","xxx"}// T是占位符,在使用的时候,必须要实例化为具体的类型。//var d Slice[T] = []int{1,2,3}
}
泛型使用案例2:
泛型可以用在所有有类型的地方
package mainimport "fmt"// 泛型可以用在所有有类型的地方type MyStruct[T int | string] struct {Id TName string
}type IprintData[T int | float64 | string] interface {Print(data T)
}// MyChan 通道
type MyChan[T int | string | float64] chan Tfunc main() {//T 泛型的参数类型的属性可以远不止一个,所有东西都可以泛型化。不一定非得用T 其他字母也可以// map(int)string// map[KEY]VALUE 类型形参(参数是不确定) KEY 、VALUE// KEY int | string , VALUE float32 | float64 约束// 类型的名字 MyMap[KEY,VALUE], 通过这一个类型,来代表多个类型!--> 泛型//map泛型就是多个参数 KEY VALUEtype MyMap[KEY int | string | float64, VALUE float32 | float64 | int | string] map[KEY]VALUE//定义了泛型后,就可以实例化出不同类型的map// map [string]float64var score MyMap[string, float64] = map[string]float64{"go": 9.9,"java": 8.0,}fmt.Println(score)// map [int]stringvar rank MyMap[int, string] = map[int]string{1: "张三",2: "王五",}fmt.Println(rank)
}
4. 特殊的泛型
package mainimport "fmt"func main() {// 特殊的泛型类型,泛型的参数时多样的,但是实际类型定义就是inttype AAA[T int | string] intvar a AAA[int] = 123var b AAA[string] = 123fmt.Println(a)fmt.Println(b)//查看类型fmt.Printf("%T\n", a)fmt.Printf("%T\n", b)//var c AAA[string] = "hello" //不能这样赋值,因为AAA的值约束的类型是int}
这里虽然使用了泛型。但是底层类型就是int,所以传int和string都可以的,但是赋值,只能是int
四、泛型函数和方法的定义和使用
1. 定义泛型函数:
单纯的泛型没啥意义。和函数结合使用, 可以使用调用者(调用者的类型可以自定义,就可以实现泛型。)
带了类型形参的函数就叫做泛型函数,极大的提高代码的灵活心,降低阅读性!
泛型函数可以处理多种类型的数据。例如,定义一个交换两个值的泛型函数:
func Swap[T any](a, b T) (T, T) { return b, a
}
使用:
package mainimport "fmt"func Swap[T any](a, b T) (T, T) {return b, a
}func main() {a, b := Swap[int](1, 2) // 显式指定类型fmt.Println(a, b) // 输出: 2 1c, d := Swap("hello", "world") // 隐式类型推断,不用写类型fmt.Println(c, d) // 输出: world hello
}
泛型可以增加代码的灵活性,降低了可读性!
Go的泛型语法糖:自动推导 (本质,就是编译器帮我们加上去了,在实际运行,这里T还是加上去的)
这种带了类型形参的函数就叫做泛型函数,极大的提高代码的灵活心,降低阅读性!
package mainimport ("fmt"
)func main() {var a int = 1var b int = 2fmt.Println(Add[int](a, b))var c float32 = 1.1var d float32 = 2.2fmt.Println(Add[float32](c, d))// 每次都去写T的类型是很麻烦的,支持自动推导!// Go的泛型语法糖:自动推导 (本质,就是编译器帮我们加上去了,在实际运行,这里T还是加上去的)fmt.Println(Add(a, b)) // T : intfmt.Println(Add(c, d)) // T : float32}// Add 真正的Add实现,传递不同的参数都是可以适配的! Add[T] T在调用的时候需要实例化
// 这种带了类型形参的函数就叫做泛型函数,极大的提高代码的灵活心,降低阅读性!
func Add[T int | float32 | float64](a T, b T) T {return a + b
}
2. 定义泛型方法:
泛型方法可以应用于泛型类型上。
针对不同类型的切片做累加和,使用泛型比较简便
package mainimport ("fmt"
)// MySlice 定义一个泛型切片
type MySlice[T int | float32 | int64] []Tfunc main() {//针对不同类型的切片都可以计算var s MySlice[int] = []int{1, 2, 3, 4}fmt.Println(s.sum())var s1 MySlice[float32] = []float32{1.0, 2.0, 3.0, 4.4}fmt.Println(s1.sum())
}// 调用者,类型是不确定的,用户传什么,她就实例化什么。 类型参数化了 , 泛型
// 没有泛型之前, 反射: reflect.ValueOf().Kind() , 也需要很多if,本质是逻辑相同的,只是类型不同!
func (s MySlice[T]) sum() T {var sum Tfor _, v := range s {sum += v}return sum
}
五、泛型约束的使用
1. 内置约束:
Go语言提供了几个内置约束,包括any(表示任何类型)和comparable(表示可以比较的类型)。
any经常用,就是一个泛型,表示了go所有的内置类型。interface{} 这里就不做太多赘述了。
comparable是一个接口,所有可比较的类型都实现了这个接口。
可比较的类型包括布尔型、数值型、字符串、指针、通道(channel)、可比较类型的数组以及所有字段都是可比较类型的结构体等。
comparable仅能用于泛型中的类型限定(type constraint),不可作为变量的类型。
看下源码
在使用comparable作为类型约束时,需要确保类型参数确实支持比较操作,否则会导致编译错误。
comparable不支持大小比较操作(如<、<=、>、>=),仅支持相等性比较(==、!=)。
结构体类型可以作为comparable使用,但前提是其所有字段都是comparable的。如果结构体包含不可比较的字段(如切片、映射类型),则整个结构体类型也不可比较。
搜索算法:
泛型也可以用于实现通用的搜索算法。例如,定义一个泛型函数来查找切片中的元素
package mainimport "fmt"func Find[T comparable](slice []T, value T) (int, bool) {for i, v := range slice {if v == value {return i, true}}return -1, false
}func main() {numbers := []int{1, 2, 3, 4, 5}index, found := Find(numbers, 3)if found {fmt.Println("Element found at index:", index) // 输出: Element found at index: 2} else {fmt.Println("Element not found")}
}
2. 自定义约束
由于约束有时候很多,我们可以定义一些自己的泛型约束(本质是一个接口)
除了内置约束外,还可以使用自定义接口作为约束条件。例如,定义一个支持加法操作的泛型函数:
package mainimport "fmt"// MyInt 泛型的约束提取定义
type MyInt interface {int | float64 | int8 | int32 // 作用域泛型的,而不是一个接口方法 这样泛型约束可以用着集中类型都可以
}// 自定义泛型
func main() {var a int = 10var b int = 20fmt.Println(GetMaxNum(a, b))
}// GetMaxNum 函数里面泛型T 用自己定义的约束MyInt
func GetMaxNum[T MyInt](a, b T) T {if a > b {return a}return b
}
3. 支持泛型衍生类型
新符号 ~,和类型一起出现的,表示支持该类型的衍生类型!
衍生类型,就是根据该类型常见的类型
package mainimport "fmt"// int8 衍生类型
type int8A int8
type int8B = int8// NewInt ~ 表示可以匹配该类型的衍生类型
type NewInt interface {~int8
}// ~
func main() {var a int8A = 8var b int8A = 56fmt.Println(GetMax(a, b))
}
func GetMax[T NewInt](a, b T) T {if a > b {return a}return b
}
六、泛型在实际项目中的应用案例
-
日志库:在日志库中,可以使用泛型来创建通用的日志记录器,支持多种日志级别和数据类型。例如,定义一个泛型日志记录器接口,并为不同类型的日志消息实现该接口。
-
数据库ORM:在数据库ORM框架中,泛型可以用于实现通用的查询和更新操作,支持多种数据类型和数据库表结构。通过定义泛型接口和方法,可以简化数据库操作的代码,提高开发效率。
-
网络框架:在网络框架中,泛型可以用于实现通用的请求处理函数和中间件,支持多种请求和响应类型。通过定义泛型类型和接口,可以方便地扩展和定制网络框架的功能。
七、泛型使用的注意事项
-
性能问题:虽然泛型提高了代码的灵活性和重用性,但在某些情况下可能会引入性能开销。因此,在使用泛型时需要权衡性能与代码可读性之间的关系。
-
类型推断:Go语言的类型推断机制在大多数情况下能够正确地推断出泛型类型参数的类型,但在某些复杂情况下可能会出现推断失败的情况。因此,在编写泛型代码时需要注意类型推断的限制和规则。
-
约束条件:在使用泛型时,需要为类型参数指定适当的约束条件,以确保它们具备必要的属性和行为。然而,由于Go语言的接口机制相对较为简单,某些复杂的约束条件可能无法通过接口来实现。因此,在定义和使用泛型时需要仔细考虑约束条件的合理性和可行性。
八、总结
Go语言的泛型特性为开发者提供了更加灵活和强大的编程工具,使得代码更加简洁、可读和可重用。通过掌握泛型的基本概念、用法和注意事项,开发者可以更好地利用泛型来优化代码结构和提高开发效率。同时,也需要注意泛型可能带来的性能开销和类型推断限制等问题,以确保代码的正确性和稳定性。
以上是关于Go语言中泛型用法的详细介绍和教程。希望本文能够帮助读者更好地理解和掌握Go语言的泛型特性,并在实际项目中灵活运用泛型来提高代码质量和开发效率。
相关文章:

【Golang】合理运用泛型,简化开发流程
✨✨ 欢迎大家来到景天科技苑✨✨ 🎈🎈 养成好习惯,先赞后看哦~🎈🎈 🏆 作者简介:景天科技苑 🏆《头衔》:大厂架构师,华为云开发者社区专家博主,…...

OpenCV单目相机内参标定C++
基于OpenCV 实现单目相机内参标定: a.使用OpenCV库实现内参标定过程。通过角点检测、亚像素角点定位、角点存储与三维坐标生成和摄像机标定分别获取左右相机的内参。 b.具体地,使用库函数检测两组图像(左右相机拍摄图像)中棋盘格…...

基于MATLAB(DCT DWT)
第三章 图像数字水印的方案 3.1 图像数字水印的技术方案 在数据库中存储在国际互联网上传输的水印图像一般会被压缩,有时达到很高的压缩比。因此,数字水印算法所面临的第一个考验就是压缩。JPEG和EZW(Embedded Zero-Tree Wavelet࿰…...

渗透基础-rcube_webmail版本探测
简介 本文介绍了开源产品RoundCube webmail邮件系统的版本探测思路,并用go语言实现工具化、自动化探测。 正文 0x01 探测思路研究 探测系统版本,最理想的方法就是系统主页html代码中有特定的字符串,比如特定版本对应的hash在主页的html代…...

linux下编译鸿蒙版boost库
我在上一篇文章中介绍了curl和openssl的编译方式(linux下编译鸿蒙版curl、openssl-CSDN博客),这篇再介绍一下boost库的编译。 未经许可,请勿转载! 一.环境准备 1.鸿蒙NDK 下载安装方式可以参考上篇文章,…...
滚雪球学Redis[6.3讲]:Redis分布式锁的实战指南:从基础到Redlock算法
全文目录: 🎉前言🚦Redis分布式锁的概念与应用场景🍃1.1 什么是分布式锁?🍂1.2 应用场景 ⚙️使用Redis实现分布式锁🌼2.1 基本思路🌻2.2 示例代码🥀2.3 代码解析 &#…...

springboot二手汽车交易平台-计算机毕业设计源码82053
目录 1 绪论 1.1研究背景 1.2研究意义 1.3国内外研究现状 2 二手汽车交易平台系统分析 2.1 可行性分析 2.2 系统流程分析 2.3 功能需求分析 2.4 性能需求分析 3 二手汽车交易平台概要设计 3.1 系统体系结构设计 3.2总体功设计 3.3子模块设计设计 3.4 数据库设计 …...
typescript 中的类型推断
在 TypeScript 中,类型推断(Type Inference)是一种编译器自动确定变量或表达式类型的能力。这大大减少了需要显式声明类型的代码量,使得代码更加简洁和易读。TypeScript 的类型推断机制非常强大,可以在很多情况下自动推…...
linux 隐藏文件
在Linux中,隐藏文件以点(.)开头的文件或文件夹被认为是隐藏文件。隐藏文件通常用于存储系统配置文件或敏感文件。 以下是几种不同的方法来隐藏文件或文件夹: 方法1:在文件或文件夹名字前面加上点(.&#…...

【网络协议栈】Tcp协议(上)结构的解析 和 Tcp中的滑动窗口(32位确认序号、32位序号、4位首部长度、6位标记位、16为窗口大小、16位紧急指针)
绪论 “没有那么多天赋异禀,优秀的人总是努力翻山越岭。”本章主要讲到了再五层网络协议从上到下的第二层传输层中使用非常广泛的Tcp协议他的协议字段结构,通过这些字段去认识其Tcp协议运行的原理底层逻辑和基础。后面将会再写一篇Tcp到底是通过什么调…...

手表玻璃盖板视觉贴合
在手表生产过程中,贴合加工是一个至关重要的环节,它涉及将手表的盖板与LCM模组或各种功能片进行精准贴合。这一过程不仅要求高度的精度,还追求效率与稳定性,以满足现代可穿戴设备日益增长的市场需求。然而,当前行业在这…...

电信和互联网行业数据安全评估师CCRC-DSA人才强基计划
“电信和互联网行业数据安全人才强基计划”(以下简称“强基计划”)自 2022 年 4 月启动伊始,始终秉持以人才需求为导向,以体系化能力建设为重点,扎实铸就数据安全人才培养品牌,力促行业数据安全人才培养工作…...

MQTTnet 4.3.7.1207 (最新版)使用体验,做成在线客服聊天功能,实现Cefsharp的物联的功能(如远程打开新网址)
一、MQTTnet 4.3.x版本客户端 将客户端集成到 cefsharp 定制浏览器中,实现物联网功能 网上很多代码是3.x版本代码,和4.x版本差异性较大,介绍较为简单或不系统 二、部分代码说明 初始化,初始化》连接服务端》发布上线信息(遗嘱)ConnectAsync等 订阅主题:SubscribeAsync 接…...

将java项目jar包打包成exe服务
1.结构展示 2.注意事项 前提: 环境准备:jdk8 和 .net支持 { 1.控制面板》程序和功能》启用和关闭windows功能》.net的勾选》2.jdk8自行百度安装环境3.其他项目必须的软件环境安装等(数据库...) }第一次准备: 1.将打包好的jar包放到premiumServices.exe…...
Django请求响应对象
在 Django 中,请求(request)和响应(response)对象是处理 HTTP 请求和返回 HTTP 响应的核心。它们分别由 Django 的 HttpRequest 和 HttpResponse 类表示。 HttpRequest 对象 HttpRequest 对象包含了客户端发送的所有…...

DevExpress中文教程 - 如何在静态SSR模式下使用Blazor Drawer组件?
Microsoft的 .NET 8 UI框架引入了静态服务器端呈现模式(静态SSR)——组件在服务器端呈现,然后返回到客户端,没有任何交互,DevExpress Blazor Drawer组件需要交互式呈现模式来动态地改变其IsOpen状态。 在本文中&#…...

商汤科技十周年公布新战略,将无缝集成算力、模型及应用
10月18日,恰逢商汤科技十周年庆典,“2024商汤十周年国际论坛:迈向AI 2.0共融新时代”在香港科学园成功举办。 据「TMT星球」了解,来自全球的行业领袖、政府代表、AI专家共聚于此,共同探讨AI行业的未来。 活动上&…...
【如何获取股票数据07】Python、Java等多种主流语言实例演示获取股票行情api接口之沪深A股历史分时MA数据获取实例演示及接口API说明文档
最最近一两年内,股票量化分析逐渐成为热门话题。而从事这一领域工作的第一步,就是获取全面且准确的股票数据。因为无论是实时交易数据、历史交易记录、财务数据还是基本面信息,这些数据都是我们进行量化分析时不可或缺的宝贵资源。我们的主要…...
Rust语法基础
注释 所有的开发者都在努力使他们的代码容易理解,但有时需要额外的解释。在这种情况下,开发者在他们的源码中留下注释,编译器将会忽略掉这些内容,但阅读源码的人可能会发现有用。 和大多数的编程语言一样,主要有一下两种: 单行注释 // 多行注释 /* */ 基本数据类型 Ru…...
AWS WAF实现API安全防护
在当今的互联网环境中,API安全防护变得越来越重要。本文将介绍如何使用AWS WAF(Web Application Firewall)来实现有效的API安全防护策略。 背景 我们有一个API服务,其URL模式如下: https://dev.example.com/bff-app/sec/v1/module-a/feature-a/sub-feature-a我们需要使用AWS…...

网络编程(Modbus进阶)
思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

YSYX学习记录(八)
C语言,练习0: 先创建一个文件夹,我用的是物理机: 安装build-essential 练习1: 我注释掉了 #include <stdio.h> 出现下面错误 在你的文本编辑器中打开ex1文件,随机修改或删除一部分,之后…...
python爬虫:Newspaper3k 的详细使用(好用的新闻网站文章抓取和解析的Python库)
更多内容请见: 爬虫和逆向教程-专栏介绍和目录 文章目录 一、Newspaper3k 概述1.1 Newspaper3k 介绍1.2 主要功能1.3 典型应用场景1.4 安装二、基本用法2.2 提取单篇文章的内容2.2 处理多篇文档三、高级选项3.1 自定义配置3.2 分析文章情感四、实战案例4.1 构建新闻摘要聚合器…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...

Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...

算法:模拟
1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) 遍历字符串:通过外层循环逐一检查每个字符。遇到 ? 时处理: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: 与…...

搭建DNS域名解析服务器(正向解析资源文件)
正向解析资源文件 1)准备工作 服务端及客户端都关闭安全软件 [rootlocalhost ~]# systemctl stop firewalld [rootlocalhost ~]# setenforce 0 2)服务端安装软件:bind 1.配置yum源 [rootlocalhost ~]# cat /etc/yum.repos.d/base.repo [Base…...

Windows安装Miniconda
一、下载 https://www.anaconda.com/download/success 二、安装 三、配置镜像源 Anaconda/Miniconda pip 配置清华镜像源_anaconda配置清华源-CSDN博客 四、常用操作命令 Anaconda/Miniconda 基本操作命令_miniconda创建环境命令-CSDN博客...

【MATLAB代码】基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),附源代码|订阅专栏后可直接查看
文章所述的代码实现了基于最大相关熵准则(MCC)的三维鲁棒卡尔曼滤波算法(MCC-KF),针对传感器观测数据中存在的脉冲型异常噪声问题,通过非线性加权机制提升滤波器的抗干扰能力。代码通过对比传统KF与MCC-KF在含异常值场景下的表现,验证了后者在状态估计鲁棒性方面的显著优…...
Python 高级应用10:在python 大型项目中 FastAPI 和 Django 的相互配合
无论是python,或者java 的大型项目中,都会涉及到 自身平台微服务之间的相互调用,以及和第三发平台的 接口对接,那在python 中是怎么实现的呢? 在 Python Web 开发中,FastAPI 和 Django 是两个重要但定位不…...