Hello, i’m making an program in which we will ask user do you want to continue ? if he enters yes then it continues and if he didn’t entered anything till 10 seconds that program will exit. We’re reading input fro Scanf, is there any option to do this?
yo,
you need to use go-func statement.
It will start a new goroutime for your function. like:
var answer string = ""
go func() {
time.Sleep(10 * time.Second)
if answer == "" {
fmt.Println("timeout")
os.Exit(0)
}
}()
fmt.Scanln(&answer)
fmt.Println("answer is " + answer)
The above code creates a race condition on answer
as one routine is writing to answer
at fmt.Scanln(..)
white the other routine is reading answer
at if answer == "" { .. }
.
Perhaps something like this:
func main() {
ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()
result := make(chan string)
go func() {
var answer string
fmt.Scanln(&answer)
result <- answer
}()
select {
case r := <-result:
fmt.Println("answer is:", r)
case <-ctx.Done():
fmt.Println("timeout")
}
}
Isn’t that what <-time.After(duration)
is for?
package main
import (
"fmt"
"time"
)
func main() {
result := make(chan string)
go func() {
var answer string
fmt.Scanln(&answer)
result <- answer
}()
select {
case <-time.After(10 * time.Second):
fmt.Println("timeout")
case r := <-result:
fmt.Println("answer is:", r)
}
}
I don’t see that go run -race
returns some issues, but if so, we can probably use Mutex here, so:
package main
import (
"fmt"
"os"
"sync"
"time"
)
func main() {
m := &sync.Mutex{}
var answer string = ""
fmt.Print("do you want to continue?: ")
go func() {
time.Sleep(10 * time.Second)
m.Lock()
isEmpty := answer == ""
m.Unlock()
if isEmpty {
fmt.Println("timeout")
os.Exit(0)
}
}()
fmt.Scanln(&answer)
fmt.Println("answer is " + answer)
}
The Mutex must wrap the the fmt.Scanln(&answer)
too - but that’s not a good idea as the fmt.Scanln
will block much longer and therefore block the mutext too.
Besides that, there is no way to cancel the the fmt.Scanln
call as it reads from os.Stdin
. So even after you get the timeout (e.g. using time.Sleep
in another go routine) there is no function to stop fmt.Scanln
.
To solve that, don’t use Scanln
on os.Stdin
directly, but read from os.Stdin
in a more unblocking way:
package main
import (
"fmt"
"time"
"bufio"
"os"
)
func main() {
stdin := make(chan string)
go func() {
reader := bufio.NewReader(os.Stdin)
// read Stdin line by line
for {
line, _ := reader.ReadString('\n')
stdin <- line
}
}()
select {
case line := <-stdin:
fmt.Println("Your input:", line)
// use fmt.Scanf(line, ...) now
case <-time.After(10 * time.Second):
fmt.Println("Timeout.")
}
}
This topic was automatically closed 90 days after the last reply. New replies are no longer allowed.