繁体   English   中英

如何将 time.Duration 类型传递给 go 函数?

[英]How to pass time.Duration type to a go function?

我正在学习 GOLANG,特别是它的并发能力。

已尝试进一步开发 worker_pool 示例之一,以便每个工作人员收到一个工作 ID 和一个工作负载,以工作的随机持续时间表示。

time.sleep 命令使用持续时间来等待分配的纳秒数,这是随机计算的。

代码看起来像这样......

//worker_pool improved example

package main

import "fmt"
import "time"
import "math/rand"

// Here's the worker, of which we'll run several
// concurrent instances. These workers will receive
// work on the `jobs` channel and send the corresponding
// results on `results`. We'll sleep a random number of seconds between
// 1 and 5 to simulate an expensive task.
func worker(id int, jobs <-chan int, loads <-chan time.Duration, results chan<- int) {
   for j := range jobs {
        fmt.Println("worker", id, "started  job", j, time.Now())
        time.Sleep(loads*time.Second)  
        fmt.Println("worker", id, "finished job", j, time.Now())
        results <- j * 2
    }
}

func main() {

    // In order to use our pool of workers we need to send
    // them work and collect their results. We make 2
    // channels for this.
    jobs := make(chan int)
    loads := make(chan time.Duration)
    results := make(chan int)

    // This starts up 3 workers, initially blocked
    // because there are no jobs yet.
    for w := 1; w <= 3; w++ {
        go worker(w, jobs, results)
    }

    // Here we send 24 `jobs` and then `close` that
    // channel to indicate that's all the work we have.
    for j := 1; j <= 24; j++ {
        jobs <- j
        r := rand.New(rand.NewSource(99))
        load := r.Int63n(5000000)
        loads <- load
    }
    close(jobs)
    close(loads)


    // Finally we collect all the results of the work.
    for a := 1; a <= 24; a++ {
        <-results
    }
}

我不断收到此错误消息...

prog.go:18:33:无法将负载(类型 <-chan int)转换为类型 time.Duration

prog.go:36:18: 没有足够的参数调用 worker have (int, chan int, chan int) want (int, <-chan int, <-chan int, chan<- int)

prog.go:45:15: 不能在发送中使用负载(int64 类型)作为 int 类型

我究竟做错了什么?

即使您修复了编译错误,您仍然会遇到问题。

//worker_pool improved example

package main

import "fmt"
import "time"
import "math/rand"

// Here's the worker, of which we'll run several
// concurrent instances. These workers will receive
// work on the `jobs` channel and send the corresponding
// results on `results`. We'll sleep a random number of seconds between
// 1 and 5 to simulate an expensive task.
func worker(id int, jobs <-chan int, loads <-chan time.Duration, results chan<- int) {
    for j := range jobs {
        fmt.Println("worker", id, "started  job", j, time.Now())
        time.Sleep(<-loads * time.Second)
        fmt.Println("worker", id, "finished job", j, time.Now())
        results <- j * 2
    }
}

func main() {

    // In order to use our pool of workers we need to send
    // them work and collect their results. We make 2
    // channels for this.
    jobs := make(chan int)
    loads := make(chan time.Duration)
    results := make(chan int)

    // This starts up 3 workers, initially blocked
    // because there are no jobs yet.
    for w := 1; w <= 3; w++ {
        go worker(w, jobs, loads, results)
    }

    // Here we send 24 `jobs` and then `close` that
    // channel to indicate that's all the work we have.
    for j := 1; j <= 24; j++ {
        jobs <- j
        r := rand.New(rand.NewSource(99))
        load := time.Duration(r.Int63n(5000000))
        loads <- load
    }
    close(jobs)
    close(loads)

    // Finally we collect all the results of the work.
    for a := 1; a <= 24; a++ {
        <-results
    }
}

游乐场: https : //play.golang.org/p/tVdlKFHunKN

输出:

worker 3 started  job 1 2009-11-10 23:00:00 +0000 UTC m=+0.000000001
worker 1 started  job 2 2009-11-10 23:00:00 +0000 UTC m=+0.000000001
worker 2 started  job 3 2009-11-10 23:00:00 +0000 UTC m=+0.000000001
worker 1 finished job 2 2009-12-27 17:05:41 +0000 UTC m=+4039541.000000001
worker 3 finished job 1 2009-12-27 17:05:41 +0000 UTC m=+4039541.000000001
worker 2 finished job 3 2009-12-27 17:05:41 +0000 UTC m=+4039541.000000001
fatal error: all goroutines are asleep - deadlock!

确实是代码有问题。

我创建的通道没有缓冲。 我为作业和结果通道添加了一个 100(每个原始示例)的缓冲区,并且程序运行正常。

//worker_pool improved example

package main

import "fmt"
import "time"
import "math/rand"

func worker(id int, jobs <-chan int, loads <-chan time.Duration, results chan<- int) {
    for j := range jobs {
        before := time.Now()
        fmt.Println("worker", id, "started  job", j)
        time.Sleep(<-loads)
        after := time.Now()
        fmt.Println("worker", id, "finished job", j, "in", after.Sub(before))
        results <- j
    }
}

func main() {

    jobs := make(chan int, 100) // Buffered channel
    loads := make(chan time.Duration)
    results := make(chan int, 100) // Buffered channel

    for w := 1; w <= 3; w++ {
        go worker(w, jobs, loads, results)
    }

    for j := 1; j <= 24; j++ {
        jobs <- j
        r := rand.New(rand.NewSource(int64(j*10)))
        loads <- time.Duration(r.Int63n(500000000)) // In nano seconds
    }
    close(jobs)
    close(loads)

    for a := 1; a <= 24; a++ {
        <-results
    }
}

游乐场: https : //play.golang.org/p/bz-JIkD1OoG

我仍然习惯了随机生成器的逻辑。 给定某个种子,它每次都返回完全相同的数字,在我看来,这违背了随机性的概念。

部分结果...

worker 3 started  job 1
worker 1 started  job 2
worker 2 started  job 3
worker 1 finished job 2 in 168.00641ms
worker 1 started  job 4
worker 3 finished job 1 in 205.826435ms
worker 3 started  job 5
worker 3 finished job 5 in 160.909863ms
worker 3 started  job 6
worker 2 finished job 3 in 381.707665ms

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM