The program that I ran:
package main
import (
"flag"
"fmt"
"os"
"os/signal"
"time"
)
var sleepSeconds string
var timeToSleep time.Duration
func init() {
flag.StringVar(&sleepSeconds, "sleep", "1s", "-sleep \"3s\"")
}
func main() {
startTime := time.Now()
fmt.Println("Start Time: ", startTime)
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt)
// Block until a signal is received.
flag.Parse()
timeToSleep, err := time.ParseDuration(sleepSeconds)
if err != nil {
fmt.Println("unable to parse the duration: ", err)
return
}
fmt.Println("Time to Sleep: ", timeToSleep)
myChan := make(chan string)
go one(myChan)
go two(myChan)
go three(myChan)
var s os.Signal
fmt.Println("Signal is, ", s)
go func() {
s = <-c
fmt.Println("After receiving Signal is, ", s)
}()
i := 0
for {
i
generatedString := fmt.Sprintf("%d", i)
fmt.Println("Generating... ", generatedString)
myChan <- generatedString
// time.Sleep(timeToSleep)
fmt.Println("Length of Channel: ", len(myChan))
if s != nil {
break
}
}
fmt.Println("Total time the program ran for: ", time.Since(startTime))
}
func one(dataCh chan string) {
for val := range dataCh {
fmt.Printf("Value received in func one: %s\n", val)
time.Sleep(timeToSleep)
}
}
func two(dataCh chan string) {
for val := range dataCh {
fmt.Printf("Value received in func two: %s\n", val)
time.Sleep(timeToSleep)
}
}
func three(dataCh chan string) {
for val := range dataCh {
fmt.Printf("Value received in func three: %s\n", val)
time.Sleep(timeToSleep)
}
}
When I run this program with the following flags(5s)
./ichan -sleep "5s" > data.txt
output is puzzling as I see the program has only run for 2.31606525s
but all 3 goroutines are supposed to be blocked at least for 5 seconds each.
data.txt is part of this repository for reference, code is also available in the same repository.
My Question is: time.Sleep() in the functions one
, two
and three
are supposed to be blocked until the duration of sleep and then consume the strings from the channel, but the observation is that sleep is not having any effect on the goroutines.
CodePudding user response:
timeToSleep, err :=
creates a new, local variable named timeToSleep that is independent of the package level variable with the same name, so the package level variable is always zero.
It seems you have missed that there is a native duration flag type: https://pkg.go.dev/flag#DurationVar
func init() {
flag.DurationVar(&timeToSleep, "sleep", 1*time.Second, `-sleep "3s"`)
}
CodePudding user response:
Working Copy of the same program
package main
import (
"flag"
"fmt"
"os"
"os/signal"
"time"
)
var sleepSeconds string
var timeToSleep time.Duration
var err error
func init() {
flag.StringVar(&sleepSeconds, "sleep", "1s", "-sleep \"3s\"")
}
func main() {
startTime := time.Now()
fmt.Println("Start Time: ", startTime)
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt)
// Block until a signal is received.
flag.Parse()
timeToSleep, err = time.ParseDuration(sleepSeconds)
if err != nil {
fmt.Println("unable to parse the duration: ", err)
return
}
fmt.Println("Time to Sleep: ", timeToSleep)
myChan := make(chan string)
go one(myChan)
go two(myChan)
go three(myChan)
var s os.Signal
fmt.Println("Signal is, ", s)
go func() {
s = <-c
fmt.Println("After receiving Signal is, ", s)
}()
i := 0
for {
i
generatedString := fmt.Sprintf("%d", i)
fmt.Println("Generating... ", generatedString)
myChan <- generatedString
// time.Sleep(timeToSleep)
fmt.Println("Length of Channel: ", len(myChan))
if s != nil {
break
}
}
fmt.Println("Total time the program ran for: ", time.Since(startTime))
}
func one(dataCh chan string) {
for val := range dataCh {
fmt.Printf("Value received in func one: %s\n", val)
time.Sleep(timeToSleep)
}
}
func two(dataCh chan string) {
for val := range dataCh {
fmt.Printf("Value received in func two: %s\n", val)
time.Sleep(timeToSleep)
}
}
func three(dataCh chan string) {
for val := range dataCh {
fmt.Printf("Value received in func three: %s\n", val)
time.Sleep(timeToSleep)
}
}