Last active
June 3, 2022 15:01
-
-
Save matthewmueller/3570c165004a3dc05085caede0e4bf5d to your computer and use it in GitHub Desktop.
Cancelable Reader. Useful for tests where you want to wait for some input, but not hang forever. (Before using, you need to change child-main.go to child/main.go)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"time" | |
) | |
func main() { | |
for i := 0; i < 10; i++ { | |
time.Sleep(1 * time.Second) | |
switch { | |
case i < 5: | |
fmt.Println("Booting") | |
case i == 5: | |
fmt.Println("Started") | |
case i > 5: | |
fmt.Println("Running") | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"bufio" | |
"context" | |
"fmt" | |
"io" | |
"log" | |
"os" | |
"os/exec" | |
"time" | |
) | |
func main() { | |
if err := run(); err != nil { | |
log.Fatal(err) | |
} | |
} | |
func run() error { | |
ctx, cancel := context.WithCancel(context.Background()) | |
defer cancel() | |
cmd := exec.CommandContext(ctx, "go", "run", "child/main.go") | |
stdout, err := cmd.StdoutPipe() | |
if err != nil { | |
return err | |
} | |
defer stdout.Close() | |
cmd.Stderr = os.Stderr | |
cmd.Env = os.Environ() | |
if err := cmd.Start(); err != nil { | |
return err | |
} | |
cr, err := getCancelableReader(stdout) | |
if err != nil { | |
return err | |
} | |
if err := scan(cr); err != nil { | |
return err | |
} | |
return cmd.Wait() | |
} | |
type cancelableReader interface { | |
io.Reader | |
SetReadDeadline(time.Time) error | |
} | |
func getCancelableReader(r io.Reader) (cancelableReader, error) { | |
if cr := r.(cancelableReader); cr != nil { | |
return cr, nil | |
} | |
return nil, fmt.Errorf("not a cancelable reader") | |
} | |
func scan(cr cancelableReader) error { | |
scanner := bufio.NewScanner(cr) | |
for scanner.Scan() { | |
if err := cr.SetReadDeadline(time.Now().Add(2 * time.Second)); err != nil { | |
return err | |
} | |
fmt.Println("scanned", scanner.Text()) | |
} | |
return scanner.Err() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment