草庐IT

go - 并发示例混淆

coder 2023-07-02 原文

我正在更深入地研究 Go 的并发性。我正在阅读的一本书给出了以下示例,它基本上从命令行参数压缩文件。

 package main

 import (
  "compress/gzip"
  "io"
  "os"
 )

 func main() {

     for _, file := range os.Args[1:] {
        compress(file)
     }

 }


 func compress(filename string) error {

     in, err := os.Open(filename)

     if err != nil {
      return err
     }

     defer in.Close()

     out, err := os.Create(filename + ".gz")

     if err != nil {
       return err
     }

     defer out.Close()

     gzout := gzip.NewWriter(out)

     _, err = io.Copy(gzout, in)

     gzout.Close()

     return err
}

然后书上解释说,如果你想处理几百个文件,保持这样肯定比你使用goroutines慢,所以对main() 函数以便使用它们:

var wg sync.WaitGroup 
var i int = -1
var file string
for i, file = range os.Args[1:] {
    wg.Add(1)
    go func(filename string) {
       compress(filename)
       wg.Done()
     }(file)
 }
 wg.Wait()
 fmt.Printf("Compressed %d files\n", i+1)

然后注意到,关于内联函数定义及其参数(文件名)的“技巧”是必要的,“因为我们在 for 循环中执行 goroutine”。

我想我不明白的是为什么需要上面的内联函数才能让它工作,不能使用下面的函数,还是我错过了一个技巧?

for i, file = range os.Args[1:] {
    wg.Add(1)

    go compress(file)

    wg.Done()

 }
 wg.Wait()
 fmt.Printf("Compressed %d files\n", i+1)

最佳答案

如果你只是执行:

compress(file)

它在同一个 goroutine 中执行,因此在该调用完成之前,您不会做任何其他事情。

所以如果你想并行处理,那么你需要使用 go 关键字启动一个新的 goroutine。

如果你这样做:

go compress(file)

然后它将启动一个新的 goroutine 来压缩每个文件。

但是,一旦 main 函数启动所有 goroutine,它就会结束执行(它不会等待所有 goroutine 完成)。

这就是他们包含 wg 调用的原因。

由于 compress 函数没有收到 WaitGroup 来调用 Done,他们实现了内联函数以调用 wg.Done() 在 goroutine 完成对该文件的压缩之后。

原因是:

go func(filename string) {
    compress(filename)
    wg.Done()
}(file)

关于go - 并发示例混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50805724/

有关go - 并发示例混淆的更多相关文章

  1. postman——集合——执行集合——测试脚本——pm对象简单示例02 - 2

    //1.验证返回状态码是否是200pm.test("Statuscodeis200",function(){pm.response.to.have.status(200);});//2.验证返回body内是否含有某个值pm.test("Bodymatchesstring",function(){pm.expect(pm.response.text()).to.include("string_you_want_to_search");});//3.验证某个返回值是否是100pm.test("Yourtestname",function(){varjsonData=pm.response.json

  2. Ruby-vips 图像处理库。有什么好的使用示例吗? - 2

    我对图像处理完全陌生。我对JPEG内部是什么以及它是如何工作一无所知。我想知道,是否可以在某处找到执行以下简单操作的ruby​​代码:打开jpeg文件。遍历每个像素并将其颜色设置为fx绿色。将结果写入另一个文件。我对如何使用ruby​​-vips库实现这一点特别感兴趣https://github.com/ender672/ruby-vips我的目标-学习如何使用ruby​​-vips执行基本的图像处理操作(Gamma校正、亮度、色调……)任何指向比“helloworld”更复杂的工作示例的链接——比如ruby​​-vips的github页面上的链接,我们将不胜感激!如果有ruby​​-

  3. ruby-on-rails - 获取并发布相同匹配项的请求 - 2

    在我的路线文件中我有:match'graphs/(:id(/:action))'=>'graphs#(:action)'如果是GET请求(工作)或POST请求(不工作),我想匹配它我知道我可以使用以下方法在资源中声明POST请求:post'/'=>:show,:on=>:member但是我怎样才能为比赛做到这一点呢?谢谢。 最佳答案 如果你同时想要POST和GETmatch'graphs/(:id(/:action))'=>'graphs#(:action)',:via=>[:get,:post]编辑默认值可以设置如下match'g

  4. arrays - 如何在下面的示例中将两个值数组分组为 n 个值数组? - 2

    我已经有很多两个值数组,例如下面的例子ary=[[1,2],[2,3],[1,3],[4,5],[5,6],[4,7],[7,8],[4,8]]我想把它们分组到[1,2,3],[4,5],[5,6],[4,7,8]因为意思是1和2有关系,2和3有关系,1和3有关系,所以1,2,3都有关系我如何通过ruby​​库或任何算法来做到这一点? 最佳答案 这是基本Bron–Kerboschalgorithm的Ruby实现:classGraphdefinitialize(edges)@edges=edgesenddeffind_maximum_

  5. ruby - Google-api-ruby-client 翻译 API 示例 - 2

    很高兴看到google代码:google-api-ruby-client项目,因为这对我来说意味着Ruby人员可以使用GoogleAPI-s来完善代码。虽然我现在很困惑,因为给出的唯一示例使用Buzz,并且根据我的实验,Google翻译(v2)api的行为必须与google-api-ruby-client中的Buzz完全不同。.我对“Explorer”演示示例很感兴趣——但据我所知,它并不是一个探索器。它所做的只是调用一个Buzz服务,然后浏览它已经知道的关于Buzz服务的事情。对我来说,Explorer应该让您“发现”所公开的服务和方法/功能,而不一定已经知道它们。我很想听听使用这个

  6. ruby - 是否有 SproutCore 或 Cappuccino 的现场演示/示例应用程序 - 2

    在他们的网站上找不到任何内容。我主要只是想看看哪个值得一试(当然是RIA)。谢谢 最佳答案 SproutCoredemos 关于ruby-是否有SproutCore或Cappuccino的现场演示/示例应用程序,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/1419788/

  7. ruby - 关于 Ruby 中 Dir[] 和 File.join() 的混淆 - 2

    我在Ruby中遇到了一个关于Dir[]和File.join()的简单程序,blobs_dir='/path/to/dir'Dir[File.join(blobs_dir,"**","*")].eachdo|file|FileUtils.rm_rf(file)ifFile.symlink?(file)我有两个困惑:首先,File.join(@blobs_dir,"**","*")中的第二个和第三个参数是什么意思?其次,Dir[]在Ruby中有什么用?我只知道它等价于Dir.glob(),但是,我对Dir.glob()确实不是很清楚。 最佳答案

  8. ruby-on-rails - Textmate 'Go to symbol' 相当于 Vim - 2

    在Railcasts上,我注意到一个非常有趣的功能“转到符号”窗口。它像Command-T一样工作,但显示当前文件中可用的类和方法。如何在vim中获取它? 最佳答案 尝试:helptags有各种程序和脚本可以生成标记文件。此外,标记文件格式非常简单,因此很容易将sed(1)或类似的脚本组合在一起,无论您使用何种语言,它们都可以生成标记文件。轻松获取标记文件(除了下载生成器之外)的关键在于格式化样式而不是实际解析语法。 关于ruby-on-rails-Textmate'Gotosymbol

  9. ruby - 如何设置自动测试以仅重新运行失败的 rspec 示例 - 2

    我对自动测试的工作方式的印象(基于cucumbergithubwiki和其他在线内容)是它应该重新运行红色示例,直到它们通过。我的问题是它会重新运行规范文件中找到失败示例的所有示例,包括通过的示例。我不想浪费时间在修复失败示例的同时重新运行通过的示例。是否可以配置自动测试以便仅运行失败的示例? 最佳答案 您需要rspec-retrygem。以下是文档中有关如何实现它的一些示例:将它应用到覆盖整个测试套件的configureblock中...RSpec.configuredo|config|config.verbose_retry=t

  10. ruby - 是否有 Rack::Session::Cookie 用法的基本示例? - 2

    我找不到任何使用Rack::Session::Cookie的简单示例,并且希望能够将信息存储在cookie中,并在以后的请求中访问它并让它过期.这些是我能找到的唯一示例:HowdoIset/getsessionvarsinaRackapp?http://rack.rubyforge.org/doc/classes/Rack/Session/Cookie.html这是我得到的:useRack::Session::Cookie,:key=>'rack.session',:domain=>'foo.com',:path=>'/',:expire_after=>2592000,:secret=

随机推荐