返回顶部
首页 > 资讯 > 精选 >Go中过滤范型集合性能怎么实现
  • 862
分享到

Go中过滤范型集合性能怎么实现

2023-07-05 10:07:50 862人浏览 独家记忆
摘要

本文小编为大家详细介绍“Go中过滤范型集合性能怎么实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“Go中过滤范型集合性能怎么实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。正文最近,我有机会在一个真实的 g

本文小编为大家详细介绍“Go中过滤范型集合性能怎么实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“Go中过滤范型集合性能怎么实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。

正文

最近,我有机会在一个真实的 golang 场景中使用泛型,同时寻找与 Stream filter(Predicate<? super T> predicate)和 python list comprehension 等同的函数。我没有依赖现有的包,而是选择自己写一个过滤函数,以达到学习的目的。

func filterStrings(collection []string, test func(string) bool) (f []string) { for _, s := range collection {  if test(s) {   f = append(f, s)  } } return}

然而,这只适用于字符串。如果我需要过滤一个整数的集合,那么我就需要另一个极其相似的函数。

这对于一个范型函数来说似乎是一个完美的选择。

func filter[T any](collection []T, test func(T) bool) (f []T) {for _, e := range collection {if test(e) {f = append(f, e)}}return}

分析类型化和范型版本之间的(少数)差异

  • 函数名后面是一个范型T的定义。

  • T被定义为任何类型。

  • 输入 slice 中元素的类型从字符串变成了T

  • 输入、输出的 clice 类型也从字符串变成了T

不多说了,让我们来写一些单元测试。首先,我需要一个随机集合(在我的例子中,是字符串)的生成器。

func generateStrinGCollection(size, strLen int) []string {var collection []stringfor i := 0; i &lt; size; i++ {collection = append(collection, strings.Repeat(fmt.Sprintf("%c", rune('A'+(i%10))), strLen))}return collection}

现在我可以写一个测试用例,判断 filterStrings 函数的输出与我的过滤范型器的输出相同。

func TestFilter(t *testing.T) {c := generateStringCollection(1000, 3)t.Run("the output of the typed and generic functions is the same", func(t *testing.T) {predicate := func(s string) bool { return s == "AAA" }filteredStrings := filterStrings(c, predicate)filteredElements := filter(c, predicate)if !reflect.DeepEqual(filteredStrings, filteredElements) {t.Errorf("the output of the two functions is not the same")}})}
=== RUN   TestFilter=== RUN   TestFilter/the_output_of_the_typed_and_generic_functions_is_the_same--- PASS: TestFilter (0.00s)    --- PASS: TestFilter/the_output_of_the_typed_and_generic_functions_is_the_same (0.00s)PASS

考虑新函数在处理大的 slice 时的性能问题。我怎样才能确保它在这种情况下也能表现良好?

答案是:基准测试。用Go编写基准测试与单元测试很相似。

const (CollectionSize = 1000ElementSize    = 3)func BenchmarkFilter_Typed_Copying(b *testing.B) {c := generateStringCollection(CollectionSize, ElementSize)b.Run("Equals to AAA", func(b *testing.B) {for i := 0; i &lt; b.N; i++ {filterStrings(c, func(s string) bool { return s == "AAA" })}})}func BenchmarkFilter_Generics_Copying(b *testing.B) {c := generateStringCollection(CollectionSize, ElementSize)b.Run("Equals to AAA", func(b *testing.B) {for i := 0; i &lt; b.N; i++ {filter(c, func(s string) bool { return s == "AAA" })}})}
go test -bench=. -count=10 -benchmemgoos: darwingoarch: arm64pkg: GitHub.com/timliudream/go-test/generic_testBenchmarkFilter_Typed_Copying/Equals_to_AAA-8             718408              1641 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Typed_Copying/Equals_to_AAA-8             718148              1640 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Typed_Copying/Equals_to_AAA-8             732939              1655 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Typed_Copying/Equals_to_AAA-8             723036              1639 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Typed_Copying/Equals_to_AAA-8             699075              1639 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Typed_Copying/Equals_to_AAA-8             707232              1643 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Typed_Copying/Equals_to_AAA-8             616422              1652 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Typed_Copying/Equals_to_AAA-8             730702              1649 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Typed_Copying/Equals_to_AAA-8             691488              1700 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Typed_Copying/Equals_to_AAA-8             717043              1646 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Generics_Copying/Equals_to_AAA-8          428851              2754 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Generics_Copying/Equals_to_AAA-8          428437              2762 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Generics_Copying/Equals_to_AAA-8          430444              2800 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Generics_Copying/Equals_to_AAA-8          429314              2757 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Generics_Copying/Equals_to_AAA-8          430938              2754 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Generics_Copying/Equals_to_AAA-8          429795              2754 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Generics_Copying/Equals_to_AAA-8          426714              2755 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Generics_Copying/Equals_to_AAA-8          418152              2755 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Generics_Copying/Equals_to_AAA-8          431739              2761 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Generics_Copying/Equals_to_AAA-8          412221              2755 ns/op            4080 B/op          8 allocs/opPASSok      github.com/timliudream/go-test/generic_test     25.005s

我对这个结果并不满意。看起来我用可读性换取了性能。

此外,我对分配的数量也有点担心。你注意到我的测试名称中的_Copying后缀了吗?那是因为我的两个过滤函数都是将过滤后的项目从输入集合复制到输出集合中。为什么我必须为这样一个简单的任务占用内存?

到最后,我需要做的是过滤原始的收集。我决定先解决这个问题。

func filterInPlace[T any](collection []T, test func(T) bool) []T {var position, size = 0, len(collection)for i := 0; i &lt; size; i++ {if test(collection[i]) {collection[position] = collection[i]position++}}return collection[:position]}

我不是把过滤后的结果写到一个新的集合中,然后再返回,而是把结果写回原来的集合中,并保留一个额外的索引,以便在过滤后的项目数上 "切 "出一个片断。

我的单元测试仍然通过,在改变了下面这行之后。

filteredStrings := filterStrings(c, predicate)//filteredElements := filter(c, predicate)filteredElements := filterInPlace(c, predicate) // new memory-savvy function

再添加一个 bench 方法

func BenchmarkFilter_Generics_InPlace(b *testing.B) { c := generateStringCollection(CollectionSize, 3) b.Run("Equals to AAA", func(b *testing.B) {  for i := 0; i &lt; b.N; i++ {   filterInPlace(c, func(s string) bool { return s == "AAA" })  } })}

结果是出色的。

go test -bench=. -benchmemgoos: darwingoarch: arm64pkg: github.com/timliudream/go-test/generic_testBenchmarkFilter_Typed_Copying/Equals_to_AAA-8             713928              1642 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Generics_Copying/Equals_to_AAA-8          426055              2787 ns/op            4080 B/op          8 allocs/opBenchmarkFilter_Generics_Inplace/Equals_to_AAA-8          483994              2467 ns/op               0 B/op          0 allocs/opPASSok      github.com/timliudream/go-test/generic_test     4.925s

不仅内存分配归零,而且性能也明显提高。

读到这里,这篇“Go中过滤范型集合性能怎么实现”文章已经介绍完毕,想要掌握这篇文章的知识点还需要大家自己动手实践使用过才能领会,如果想了解更多相关内容的文章,欢迎关注编程网精选频道。

--结束END--

本文标题: Go中过滤范型集合性能怎么实现

本文链接: https://lsjlt.com/news/351038.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • Go中过滤范型集合性能怎么实现
    本文小编为大家详细介绍“Go中过滤范型集合性能怎么实现”,内容详细,步骤清晰,细节处理妥当,希望这篇“Go中过滤范型集合性能怎么实现”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。正文最近,我有机会在一个真实的 G...
    99+
    2023-07-05
  • Go中过滤范型集合性能示例详解
    目录正文分析类型化和范型版本之间的(少数)差异再添加一个 bench 方法正文 最近,我有机会在一个真实的 Golang 场景中使用泛型,同时寻找与 Stream filter(P...
    99+
    2023-03-08
    Go过滤范型集合 Go 范型性能
  • Grafana中怎么实现数据过滤和聚合
    在Grafana中实现数据过滤和聚合可以通过查询语句和面板设置来实现。以下是一些常见的方法: 使用查询语句中的WHERE...
    99+
    2024-04-02
  • PHP中怎么实现数据过滤
    本篇文章给大家分享的是有关PHP中怎么实现数据过滤,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。PHP数据过滤调度方法这种方法是用一个单一的PHP脚本调度(通过 URL)。其他...
    99+
    2023-06-17
  • android下拉框过滤功能怎么实现
    在Android中实现下拉框的过滤功能可以通过以下步骤来实现: 创建一个下拉框(Spinner)和一个适配器(Adapter)来管...
    99+
    2024-03-04
    android
  • 怎么理解Java中List集合性能
    本篇内容介绍了“怎么理解Java中List集合性能”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!List是一个元素有序,可重复集合,集合中每...
    99+
    2023-06-02
  • Django模板中怎么实现过滤器
    这篇文章主要介绍了Django模板中怎么实现过滤器,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。模版常用过滤器在模版中,有时候需要对一些数据进行处理以后才能使用。一般在Pyt...
    99+
    2023-06-15
  • ASP.NET Core MVC中怎么实现过滤器
    本篇内容介绍了“ASP.NET Core MVC中怎么实现过滤器”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!过滤器如何...
    99+
    2023-06-29
  • MongoDB中怎么实现where条件过滤
    这期内容当中小编将会给大家带来有关MongoDB中怎么实现where条件过滤,文章内容丰富且以专业的角度为大家分析和叙述,阅读完这篇文章希望大家可以有所收获。 实际上习...
    99+
    2024-04-02
  • Redis中的布隆过滤器怎么实现
    这篇文章主要介绍“Redis中的布隆过滤器怎么实现”,在日常操作中,相信很多人在Redis中的布隆过滤器怎么实现问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”Redis中的布...
    99+
    2024-04-02
  • 怎么在java中使用Filter实现过滤
    今天就跟大家聊聊有关怎么在java中使用Filter实现过滤,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。Java是什么Java是一门面向对象编程语言,可以编写桌面应用程序、Web应...
    99+
    2023-06-14
  • C++中怎么实现遍历集合
    C++中怎么实现遍历集合,针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。在Java中,常见的遍历集合方式如下:Iterator iter = l...
    99+
    2023-06-17
  • 为何在Go语言中难以实现类似集合的功能?
    在Go语言中难以实现类似集合的功能,是一个困扰许多开发者的问题。相比其他编程语言如Python或Java,Go语言并没有内置的集合类型,如set、map等,这给开发者在实现集合功能时带...
    99+
    2024-04-02
  • Python中怎么用django filter实现多条件过滤
    在Django中,可以使用`filter()`方法实现多条件过滤。`filter()`方法接收一个或多个条件表达式作为参数,并返回符...
    99+
    2023-10-25
    Python django
  • java中怎么实现List集合去重
    本篇内容介绍了“java中怎么实现List集合去重”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!前言:List 去重指的是将 List 中的...
    99+
    2023-06-30
  • Go中怎么用Routines实现高性能HTTP服务器
    在Go中使用Routines实现高性能HTTP服务器的步骤如下: 1、创建一个HTTP服务器实例并监听指定的端口号: package...
    99+
    2024-04-18
    Go 服务器
  • Go怎么整合captcha实现验证码功能
    这篇“Go怎么整合captcha实现验证码功能”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Go怎么整合captcha实现验...
    99+
    2023-07-05
  • C#中怎么实现多个集合的交集查找
    在C#中,可以使用LINQ来实现多个集合的交集查找。首先,将多个集合合并到一个集合中,然后使用LINQ的Intersect方法来查找...
    99+
    2024-04-02
  • vue-cli 3中怎么实现一个全局过滤器
    vue-cli 3中怎么实现一个全局过滤器,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。1、创建 filters.js首先新建一个filter...
    99+
    2024-04-02
  • Python中怎么实现数学集合运算
    这篇文章将为大家详细讲解有关Python中怎么实现数学集合运算,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。&lsquo;union()&rsquo;返回一个新集合...
    99+
    2023-06-16
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作