【问题标题】:Channel accepting value only once - golang频道只接受一次价值 - golang
【发布时间】:2014-09-17 22:54:10
【问题描述】:

我刚刚开始使用 go。这是我试图通过以下代码实现的目标。

Main 函数为 searchAndLog() 创建 5 个线程。这个函数接受一个通道,通过这个通道它会接收到一个目录的路径,它会搜索一个名为“.DS_Store”的文件,然后用它做一些事情。

main 函数然后为 "file path.Walk()" 创建另一个线程。该线程将遍历传递给它的目录,并且对于它遇到的每个目录(在 walkFunc() 中),它将执行选择语句,将目录路径传递给 5 个线程之一。

但是当我运行这个程序时,"filepath.Walk()" 遇到的前五个目录将它传递给五个线程,但是一旦它将一个目录传递给每个线程一次,它停止了。选择中的通道 dir[0]dir[5] 不会第二次接受值。

我做错了什么?

package main

// A simple multithreaded program to calculate how many
// and total disk space occupyed by all ".DS_Store" files.
// It also logs the location of each file along with its
// size

import (
  "fmt"
  "io/ioutil"
  "os"
  "flag"
  "path/filepath"
)

// Returns true if path is a directory otherwise false
func isDirectory(path string) bool {
  file, err := os.Open(path)
  if err != nil {
    fmt.Println(err)
    return false
  }
  defer file.Close()
  fi, err := file.Stat()
  if err != nil {
    fmt.Println(err)
    return false
  }
  return (fi.Mode()).IsDir()
}

func main() {

  // Command line flag to pass in how many threads to swapn
  var numThreads int
  flag.IntVar(&numThreads, "t", 5, "number of threads")
  flag.Parse()
  fmt.Println("numThreads: ", numThreads)

  // 5 Channels for 5 threads
  var dir [5]chan string
  for i, _ := range dir {
    dir[i] = make(chan string)
  }

  // This is the function that will be passed to filepath.Walk()
  // "select" will be executed only if path points to directory
  walkFunc := func(path string, info os.FileInfo, err error) error {
    fmt.Println("Visited: ", path)
    if isDirectory(path) {
      select {
        case dir[0] <- path:
          fmt.Println("Thread: 1")
        case dir[1] <- path:
          fmt.Println("Thread: 2")
        case dir[2] <- path:
          fmt.Println("Thread: 3")
        case dir[3] <- path:
          fmt.Println("Thread: 4")
        case dir[4] <- path:
          fmt.Println("Thread: 5")
        }
    }
    return nil
  }

  // Create 5 threads of searchAndLog()
  for i := 0; i < numThreads; i++ {
    go searchAndLog(dir[i], i)
  }

  go filepath.Walk("/Users/nikhil/Workspace", walkFunc)

  var input string
  fmt.Scanln(&input)
}

// id is passed to identify the thread in the println statements
func searchAndLog(dirpath chan string, id int) {
  directory := <- dirpath
  fmt.Println("Thread # ", id + 1, directory)
  files, _ := ioutil.ReadDir(directory)
  for _, f := range files {
    if f.Name() == ".DS_Store" {
      fmt.Println("Thread # ", id + 1, f.Size())
    }
  }
}

编辑:正如 Damsham 指出的那样,线程在接受一次值后退出。用他建议修复代码的代码替换线程创建循环。

【问题讨论】:

    标签: go channel


    【解决方案1】:

    因为一旦searchAndLog 在频道上接收到一些东西,它就会完成它的工作并退出。因此,在 5 个目录之后,所有运行 searchAndLog 的 goroutine 现在都消失了。试试这个:

    // Create 5 threads of searchAndLog()
    for i := 0; i < numThreads; i++ {
      go func(i int) {
         for {
            searchAndLog(dir[i], i)
         }
      }(i)
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-09-27
      • 2019-02-02
      • 2018-08-20
      • 2016-04-05
      • 2018-03-15
      • 1970-01-01
      相关资源
      最近更新 更多