Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/r/65.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Generics Golang效率中的非泛型映射_Generics_Map_Go - Fatal编程技术网

Generics Golang效率中的非泛型映射

Generics Golang效率中的非泛型映射,generics,map,go,Generics,Map,Go,我完全理解Go不支持泛型,而是让用户在需要时创建自己的类型特定方法 但是,我想知道是否有一种更有效的方法可以在数据结构上生成一个特定的映射函数,而不需要遍历整个列表并应用该函数,或者这就是其他支持泛型的语言在幕后所做的 例如: func map(list []string, op func(string)string) []string { ouput := make([]string, len(list)) for i, v := range list { output[i]

我完全理解Go不支持泛型,而是让用户在需要时创建自己的类型特定方法

但是,我想知道是否有一种更有效的方法可以在数据结构上生成一个特定的
映射
函数,而不需要遍历整个列表并应用该函数,或者这就是其他支持泛型的语言在幕后所做的

例如:

func map(list []string, op func(string)string) []string {
  ouput := make([]string, len(list))
  for i, v := range list {
    output[i] = op(v)
  }
  return output
}

谢谢

仅供参考,
map
是一个保留字,因此您不能使函数完全像使用小写
map
编写的那样

这可能是你能得到的最好的了。泛型无法让您分配新内存

使用append()比在开始时将整个片段初始化为空字符串要快一些。例如:

func Map(list []string, op func(string) string) []string {
   output := make([]string, 0, len(list))
   for _, v := range list {
      output = append(output, op(v))
   }
   return output
}
这使我的速度提高了约10%

更新:这只适用于非常短的切片。这里有一个更全面的基准测试——在较长的切片上使用append实际上较慢。我还尝试了并行化,这只值得在更大的片上增加开销

代码:

输出(测试名称末尾的数字为切片长度):


是的,通常这正是泛型的用途。如果您愿意,这样的函数仍然可以使用反射在Go中编写,尽管它们要慢得多。例如,请参阅my package,它使用反射来实现经典的泛型函数。我实际上还没有对它们进行基准测试,尽管如果它们的性能接近您提供的特定类型实现的性能,我会非常惊讶

编辑:为了好玩,我复制了韦斯·弗里曼的第一个测试,并在我基于反射的地图上运行了它。这是在一个动力不足的服务器上运行的,但仍然是。结果不言而喻(慢度是根据韦斯的结果来衡量的)


注意:我特别使用了这个测试,因为我的实现预先分配了片。

我无法确认您的基准测试结果。我觉得他们难以置信。请发布您的基准代码和结果。您是对的,这只是非常小的片段的情况。即将更新我的答案。如果我做错了什么,请撕开基准测试。:)回答得很好,谢谢你的仔细回答。所以,我想外卖是没有“黄金子弹”优化地图,一般的方法(制作或附加)是“足够快”。是的,我同意你的外卖。这是一个有趣的练习我用int交换了字符串片段,差别甚至更大。如果你感兴趣的话,我想你的观察是对的:这个映射(和过滤器)是对几行琐碎代码的抽象。在0.1%的时间里,你需要一些更快的东西,很容易产生一堆goroutine来完成这项工作——只需要多一点点代码。
go test -bench=".*" -test.cpu=2
BenchmarkSliceMake10-2       5000000           473 ns/op
BenchmarkSliceMake100-2       500000          3637 ns/op
BenchmarkSliceMake1000-2       50000         43920 ns/op
BenchmarkSliceMake10000-2       5000        539743 ns/op
BenchmarkSliceAppend10-2     5000000           464 ns/op
BenchmarkSliceAppend100-2     500000          4303 ns/op
BenchmarkSliceAppend1000-2     50000         51172 ns/op
BenchmarkSliceAppend10000-2     5000        595650 ns/op
BenchmarkSlicePar10-2         500000          3784 ns/op
BenchmarkSlicePar100-2        200000          7940 ns/op
BenchmarkSlicePar1000-2        50000         50118 ns/op
BenchmarkSlicePar10000-2        5000        465540 ns/op
BenchmarkSliceMake10-2    200000         14091 ns/op [30.0x    slower]
BenchmarkSliceMake100-2    10000        112137 ns/op [30.83x   slower]
BenchmarkSliceMake1000-2    2000       1177498 ns/op [26.810x  slower]
BenchmarkSliceMake10000-2    100      11513085 ns/op [21.3307x slower]