func StdinRead (cmds map[string]func([]string), unhandled *func([]string)) {
reader := bufio.NewReader(os.Stdin)
for {
text, err := reader.ReadString('\n')
if err!=nil {
fmt.Printf("%+v\n", err)
continue
}
text = strings.TrimSpace(text)
args := strings.Split(text, " ")
if len(args)<1 {
continue
}
if fn, ok := cmds[args[0]]; ok {
fn(args[1:])
} else if unhandled!=nil {
h := *unhandled
h(args)
} else {
fmt.Printf("unhandled: '%s' %v\n", args[0], args[1:])
}
}
}
func StdinQuit () {
fmt.Println("Quiting the app, see you!")
os.Stdin.Close() // force close stdin, otherwise the process hangs in the next for loop
time.Sleep(time.Second * 200)
}package main
import(
"fmt"
"bufio"
"strings"
"os"
"os/signal"
"syscall"
"time"
)
func main () {
EOApp := Quiter{}
go EOApp.Read()
cmds := make(map[string] func([]string))
cmds["hello"] = func (s []string) {
fmt.Println("hello buddy!")
}
cmds["serve"] = func (s []string) {
// fmt.Println("hello buddy!")
}
cmds["ping"] = func (s []string) {
// fmt.Println("hello buddy!")
}
unhandled := func (s []string) {
if s[0]!="" {
fmt.Printf("nop, i don t know this command: '%s' %v\n", s[0], s[1:])
}
}
EOApp.Register(StdinQuit)
StdinRead(cmds, &unhandled)
}
func StdinRead (cmds map[string]func([]string), unhandled *func([]string)) {
reader := bufio.NewReader(os.Stdin)
for {
text, err := reader.ReadString('\n')
if err!=nil {
fmt.Printf("%+v\n", err)
continue
}
text = strings.TrimSpace(text)
args := strings.Split(text, " ")
if len(args)<1 {
continue
}
if fn, ok := cmds[args[0]]; ok {
fn(args[1:])
} else if unhandled!=nil {
h := *unhandled
h(args)
} else {
fmt.Printf("unhandled: '%s' %v\n", args[0], args[1:])
}
}
}
func StdinQuit () {
fmt.Println("Quiting the app, see you!")
os.Stdin.Close() // force close stdin, otherwise the process hangs in the next for loop
time.Sleep(time.Second * 200)
}
type Quiter struct {
Components []func()
}
func (q *Quiter) Register (component func()) int {
q.Components = append(q.Components, component)
return len(q.Components)-1
}
func (q *Quiter) exitComponents () {
for _, component := range q.Components {
component()
}
}
func (q *Quiter) Read () {
c := make(chan os.Signal)
signal.Notify(c, os.Interrupt, syscall.SIGTERM)
signalSent := 0
for {
select {
case <-c:
if signalSent <1 {
go func () {
q.exitComponents()
os.Exit(1)
}()
} else {
fmt.Println("Force shutdown")
os.Exit(1)
}
signalSent++
}
}
}
Package signal will not block sending to c: the caller must ensure that c has sufficient buffer space to keep up with the expected signal rate. For a channel used for notification of just one signal value, a buffer of size 1 is sufficient.
Unfortunately POSIX does not guarantee that close from one thread will unblock another.
On Wed, Aug 31, 2016 at 11:58 PM, adonovan via golang-nuts
<golan...@googlegroups.com> wrote:
>
> [the POSIX 'select' system call] was the inspiration for the Go
> select statement, but whereas Go's select multiplexes channels,
> POSIX's select multiplexes files.
I can't claim any authority over this, but believe it is wrong. The
control structure appeared in Tony Hoare's communicating sequential
processes [...]
I dig into the repo you mentioned, TBHonnest, im not that wise, and it remains unclear.
For the few i know, select is the approach to take, but the API is unclear.
Not sure if it s possible to come up with something as straight as `NewReader(os.Stdin).Block(false).Read()`