简体   繁体   中英

Why does the goroutine not block for time.Sleep(duration)

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.

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"`)
}

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)
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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