Skip to content

Instantly share code, notes, and snippets.

@Static-Flow
Created September 1, 2023 13:59
Show Gist options
  • Select an option

  • Save Static-Flow/e32ded2b8037bde37a7e747abb2239bc to your computer and use it in GitHub Desktop.

Select an option

Save Static-Flow/e32ded2b8037bde37a7e747abb2239bc to your computer and use it in GitHub Desktop.
simple solution to solve wanting a variable N number of receivers to an io.Writer in Golang
package main
import (
"bufio"
"fmt"
"io"
"log"
"os/exec"
"sync"
"time"
)
type Job struct {
Command string
mutex sync.Mutex
monitors map[int]io.Writer
}
func (j *Job) AddMonitor(id int, writer io.Writer) {
j.mutex.Lock()
j.monitors[id] = writer
j.mutex.Unlock()
}
func (j *Job) RemoveMonitor(id int) {
j.mutex.Lock()
delete(j.monitors, id)
j.mutex.Unlock()
}
func (j *Job) Run() {
reader, writer := io.Pipe()
bufferedReader := bufio.NewReader(reader)
osCmd := exec.Command("/bin/bash", "-c", j.Command)
osCmd.Stdout = writer
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
if err := osCmd.Run(); err != nil {
log.Fatalln(err)
}
writer.Close()
}()
buf := make([]byte, 1024)
var n int
var err error
for {
n, err = bufferedReader.Read(buf)
if err != nil {
if err == io.EOF {
break
}
fmt.Println("Error reading from buffer:", err)
return
}
j.mutex.Lock()
for _, monitor := range j.monitors {
if _, err = monitor.Write(buf[:n]); err != nil {
log.Fatalln("Could not send to writer")
}
}
j.mutex.Unlock()
}
// Wait for the command to complete
wg.Wait()
}
func CreateMonitor(index int) io.Writer {
reader, writer := io.Pipe()
bufferedReader := bufio.NewReader(reader)
go func() {
for {
buf := make([]byte, 1024)
var n int
var err error
n, err = bufferedReader.Read(buf)
if err != nil {
if err == io.EOF {
break
}
fmt.Println("Error reading from buffer:", err)
return
}
fmt.Println(fmt.Sprintf("Monitor %d read: %s", index, buf[:n]))
}
}()
return writer
}
func main() {
j := &Job{
Command: "while true; do echo 'data'; sleep 1; done",
monitors: map[int]io.Writer{},
}
go j.Run()
for i := 0; i < 5; i++ {
j.AddMonitor(i,CreateMonitor(i))
}
for i := 4; i >= 0; i-- {
time.Sleep(5*time.Second)
fmt.Println("removing monitor: ",i)
j.RemoveMonitor(i)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment