当前位置: 首页 > 面试题库 >

在Golang中同时读取文件

钮长恨
2023-03-14
问题内容

阅读部分不是并发的,但处理是并发的。我用这种方式来命名标题,因为我最有可能使用该短语再次搜索此问题。:)

尝试 超越示例 之后,我陷入僵局,因此这对我来说是一种学习经验。我的目标是:

  1. 逐行读取文件(最终使用缓冲区执行多行)。
  2. 将文本传递给func()执行某些正则表达式的工作。
  3. 将结果发送到某个地方,但要避免使用互斥或​​共享变量。我正在将整数(总是数字1)发送到通道。这有点愚蠢,但是如果不引起问题,除非您有更整洁的选择,否则我想像这样保留它。
  4. 使用工作池执行此操作。我不确定如何告诉工人重新排队?

这是游乐场的链接。我试图写出有用的评论,希望这很有道理。我的设计可能是完全错误的,所以请毫不犹豫地进行重构。

package main

import (
  "bufio"
  "fmt"
  "regexp"
  "strings"
  "sync"
)

func telephoneNumbersInFile(path string) int {
  file := strings.NewReader(path)

  var telephone = regexp.MustCompile(`\(\d+\)\s\d+-\d+`)

  // do I need buffered channels here?
  jobs := make(chan string)
  results := make(chan int)

  // I think we need a wait group, not sure.
  wg := new(sync.WaitGroup)

  // start up some workers that will block and wait?
  for w := 1; w <= 3; w++ {
    wg.Add(1)
    go matchTelephoneNumbers(jobs, results, wg, telephone)
  }

  // go over a file line by line and queue up a ton of work
  scanner := bufio.NewScanner(file)
  for scanner.Scan() {
    // Later I want to create a buffer of lines, not just line-by-line here ...
    jobs <- scanner.Text()
  }

  close(jobs)
  wg.Wait()

  // Add up the results from the results channel.
  // The rest of this isn't even working so ignore for now.
  counts := 0
  // for v := range results {
  //   counts += v
  // }

  return counts
}

func matchTelephoneNumbers(jobs <-chan string, results chan<- int, wg *sync.WaitGroup, telephone *regexp.Regexp) {
  // Decreasing internal counter for wait-group as soon as goroutine finishes
  defer wg.Done()

  // eventually I want to have a []string channel to work on a chunk of lines not just one line of text
  for j := range jobs {
    if telephone.MatchString(j) {
      results <- 1
    }
  }
}

func main() {
  // An artificial input source.  Normally this is a file passed on the command line.
  const input = "Foo\n(555) 123-3456\nBar\nBaz"
  numberOfTelephoneNumbers := telephoneNumbersInFile(input)
  fmt.Println(numberOfTelephoneNumbers)
}

问题答案:

您快要准备好了,只需要在goroutine的同步上做一些工作即可。您的问题是您试图在相同的例程中提供解析器并收集结果,但这无法完成。

我提出以下建议:

  1. 在单独的例程中运行扫描仪,读取所有内容后关闭输入通道。
  2. 运行单独的例程,等待解析器完成工作,然后关闭输出通道。
  3. 在主例程中收集所有结果。

相关更改如下所示:

// Go over a file line by line and queue up a ton of work
go func() {
    scanner := bufio.NewScanner(file)
    for scanner.Scan() {
        jobs <- scanner.Text()
    }
    close(jobs)
}()

// Collect all the results...
// First, make sure we close the result channel when everything was processed
go func() {
    wg.Wait()
    close(results)
}()

// Now, add up the results from the results channel until closed
counts := 0
for v := range results {
    counts += v
}

在操场上完全可用的示例:http :
//play.golang.org/p/coja1_w-fY

值得补充的是,您不一定需要WaitGroup实现相同的目标,您需要知道的是何时停止接收结果。例如,可以通过扫描仪广告(在频道上)读取多少行,然后收集器仅读取指定数量的结果(您也需要发送零)来实现。



 类似资料:
  • 问题内容: 我是Golang的新手。现在,我正在尝试找出如何在Golang中建立任意一对一频道的方法,其设置如下: 说我有两个goroutines numgen1和numgen2同时执行并将数字写入通道num1resp。num2。我想在新进程addnum中添加从numgen1和numgen2发送的数字。我已经尝试过这样的事情: 但这似乎令人遗憾。有人可以给我一些想法吗? 非常感谢您的帮助。 问题答

  • 我想读取一个文件,并使用FileReader对象将其转换为base64编码的字符串。以下是我使用的代码: 但是在这种情况下,我在事件处理程序(onLoadend事件)中得到转换的结果。我想要一个同步方法。有没有办法"readAsDataURL"方法可以直接返回'result_base64'变量的值?

  • 问题内容: type ValidationModel struct { Name string Email string Password string } 首先,我使用govalidator验证请求正文。 在验证了请求之后,我再次将请求主体解码为用户结构,但已使用validationModel读取了请求主体一次,因此当我尝试再次将其解码为用户时,它没有提供任何值。 我在这里可以想到两种解决方案:

  • 我正在逐行读取一个文件,并试图使它符合特定参数的行(在我的例子中,如果它以某个单词开头),我可以覆盖该行。 谢了!

  • 问题内容: 我有一个平面文件,其中包含339276行文本,大小为62.1 MB。我试图读取所有行,根据我所具有的某些条件解析它们,然后将它们插入数据库。 我最初尝试使用bufio.Scan()循环和bufio.Text()来获取行,但我的缓冲区空间不足。我切换到使用bufio.ReadLine / ReadString / ReadByte(我尝试了每种方法),并且每种方法都有相同的问题。我没有足

  • 我有两个输入文件,分别是File1和File2。File1包含部分记录,其余部分记录分散到File2,为了创建一条记录,我需要同时读取File1和File2。每条记录的唯一键将位于记录之前的File1和File2中。请您帮助我们如何使用Spring batch reader实现此功能。