首页 > 解决方案 > time.After 在指定时间后没有被触发

问题描述

我正在使用go1.10 darwin/amd64并尝试使用以下代码片段在运行时为我的测试设置自定义超时。

我正在使用命令执行测试,将 Go 的超时设置为 11m 并将测试的恐慌计时器设置为 5m,并观察到 ​​Go 超时值被触发而不是我的。

go test github.com/foo -run TestMod -v --race -timeout 11m
...
...
*** Test killed with quit: ran too long (12m0s).

代码片段:

// Returns time.Duration from given string
// Default return value: "2h0m0s"
func GetDuration(timeoutStr string) time.Duration {
    // Default timeout to 2 hours
    durationToReturn := (2 * time.Hour)

    pattern, _ := regexp.Compile("^([0-9]+)([mhd])$")

    // Calculates only if valid pattern exists
    if pattern.MatchString(timeoutStr) {
        match := pattern.FindStringSubmatch(timeoutStr)
        timeoutVal, err := strconv.Atoi(match[1])
        if err != nil {
            return durationToReturn
        }
        timeoutDuration := time.Duration(timeoutVal)
        switch match[2] {
        case "m":
            durationToReturn = timeoutDuration * time.Minute
        case "h":
            durationToReturn = timeoutDuration * time.Hour
        case "d":
            durationToReturn = timeoutDuration * (time.Hour * 24)
        }
    }
    return durationToReturn
}

// Starts timeout trigger based on given value in suiteData.Timeout
func StartTimeoutTimer() {
    timeoutStr := "5m"
    go func() {
        timeoutDuration := GetDuration(timeoutStr)
        fmt.Printf("Setting timeout of %v from %v\n", timeoutDuration, time.Now())
        <-time.After(timeoutDuration)
        fmt.Printf("Timeout happened at %v\n", time.Now())
        panic("Test timed out..")
    }()
}

func TestMain(m *testing.M) {
    StartTimeoutTimer()
    for {
    }
}

标签: gotime

解决方案


不能保证新的 goroutineStartTimeoutTimer()会被执行。StartTimeoutTimer()创建新的 goroutine 后立即返回。

我想你想要的是

done := make(chan struct{})
go func(){
    testFunc()
    close(done)
}()
select {
    case <- time.After(duration):
        panic("...")
    case <- done:
}

推荐阅读