Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

timeout example is unsuitable #4

Closed
kele1997 opened this issue Mar 17, 2021 · 1 comment
Closed

timeout example is unsuitable #4

kele1997 opened this issue Mar 17, 2021 · 1 comment

Comments

@kele1997
Copy link

// timeout for the whole conversation
timeout := time.After(5 * time.Second)
for {
select {
case s := <-c:
fmt.Println(s)
case <-timeout:
fmt.Println("You talk too much.")
return
}
}

We always think timeout as the time that one service has on response. In this case, timeout 's meaning should be ** we don't receive any message from c channel for 5 seconds.

so maybe the right code is :

timeout := time.After(5 * time.Second)
for {
       select {
       case s := <-c:
               fmt.Println(s)
               timeout = time.After(5 * time.Second) // update timeout time
       case <-timeout:
               fmt.Println("channel has no response for 5 seconds")
               return
       }
}

the origin code seems that you want to receive from every channel for same time, like linux cfs scheduler. so maybe in that case we should use ticker

package main

import (
        "fmt"
        "time"
)

func boring(id int) <-chan string {
        c := make(chan string)
        go func() {
                 c <- "" // skip the first time
                for i := 0; ; i++ {
                        c <- fmt.Sprintf("%d, %s", id, time.Now().Format("2006-01-02 15:04:05"))
                        time.Sleep(1 * time.Second)
                }
        }()
        return c
}

func main() {
        timeout := time.NewTicker(5 * time.Second)
        c1 := boring(1)
        c2 := boring(2)
        jobchannels := []<-chan string{c1, c2}
        i := 0
        for {
                select {
                case s := <-jobchannels[i]:
                        fmt.Println(s)
                case <-timeout.C:
                        fmt.Printf("%d has talk for 5 secs\n", i+1)
                        i = (i + 1) % len(jobchannels)
                }
        }
}

and it's output is


1, 2021-03-17 11:27:03
1, 2021-03-17 11:27:04
1, 2021-03-17 11:27:05
1, 2021-03-17 11:27:06
1, 2021-03-17 11:27:07
1 has talk for 5 secs

2, 2021-03-17 11:27:08
2, 2021-03-17 11:27:09
2, 2021-03-17 11:27:10
2, 2021-03-17 11:27:11
2, 2021-03-17 11:27:12
2 has talk for 5 secs
1, 2021-03-17 11:27:08
1, 2021-03-17 11:27:14
1, 2021-03-17 11:27:15
1, 2021-03-17 11:27:16
....
@raodong
Copy link

raodong commented Mar 18, 2021

I think this example does what it intends to, which is to run for a duration of timeout from the start , as the select is wrapped in an infinite loop.
If the intention is to give an example of waiting for a fixed timeout for each request(such as get a string from boring goroutine), he will write

for {
       select {
       case s := <-c:
               fmt.Println(s)
       case <-time.After(5 * time.Second):
               fmt.Println("channel has no response for 5 seconds, you talk too slow")
               return
       }
}

which does refresh the timer in each select.
inferred from the example code fmt.Println("You talk too much.") , this is more likely to run for a fixed period of time and
get a bunch of responses before quit, but not an example of timeout for each single request, cause that would happen at the first request, which make the talk too much part nonsense

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants