Search code examples
gouser-interfaceconsoleoutputgoroutine

How to make goroutines output in multiple different consoles?


I am practicing using goroutines and found that if both goroutines are printing at the same time, it becomes difficult to read.

func main() {
    s1 := rand.NewSource(time.Now().UnixNano())
    r1 := rand.New(s1)
    wg := &sync.WaitGroup{}
    t1 := func(wg *sync.WaitGroup) {
        for i := 0; i < 100; i++ {
            time.Sleep(time.Microsecond * time.Duration(r1.Intn(100)))
            fmt.Println("T1 : ", i)
        }
        wg.Done()
    }
    t2 := func(wg *sync.WaitGroup) {
        for i := 0; i < 100; i++ {
            time.Sleep(time.Microsecond * time.Duration(r1.Intn(100)))
            fmt.Println("T2 : ", i)
        }
        wg.Done()
    }
    wg.Add(2)
    go t1(wg)
    go t2(wg)
    wg.Wait()
}

Output:

T1 :  0
T2 :  0
T2 :  1
T1 :  1
T1 :  2
T2 :  2
T1 :  3
T2 :  3
T1 :  4
T2 :  4
T1 :  5
T2 :  5
T1 :  6
T2 :  6
T2 :  7
T1 :  7
T2 :  8
T1 :  8
T1 :  9
T2 :  9
T2 :  10
T1 :  10
......

Is there any way to open multiple consoles and let two goroutines output in different consoles?


Solution

    1. You may use a simple TCP terminal server- first run this TCP terminal server and you don't need to close it as long as you need ( or just use Netcat Command: nc -l 8080 then goto #2 and write to this TCP connection e.g. "127.0.0.1:8080"):
    package main
    
    import (
        "io"
        "log"
        "net"
        "os"
    )
    
    func main() {
        ln, err := net.Listen("tcp", "127.0.0.1:8080")
        if err != nil {
            log.Fatal(err)
        }
        for {
            w1, err := ln.Accept()
            if err != nil {
                log.Fatal(err)
            }
            io.Copy(os.Stdout, w1)
            w1.Close()
        }
    }
    
    1. Then add this to your code:
        w1, err := net.Dial("tcp", "127.0.0.1:8080")
        if err != nil {
            log.Fatal(err)
        }
        defer w1.Close()
    
    1. Then use w1 as your another io.Writer in your code e.g. fmt.Fprintln(w1, "T1 : ", i), an example:
    package main
    
    import (
        "fmt"
        "log"
        "math/rand"
        "net"
        "sync"
        "time"
    )
    
    func main() {
        w1, err := net.Dial("tcp", "127.0.0.1:8080")
        if err != nil {
            log.Fatal(err)
        }
        defer w1.Close()
    
        // your code:
        s1 := rand.NewSource(time.Now().UnixNano())
        r1 := rand.New(s1)
        wg := &sync.WaitGroup{}
        t1 := func(wg *sync.WaitGroup) {
            for i := 0; i < 100; i++ {
                time.Sleep(time.Microsecond * time.Duration(r1.Intn(100)))
                fmt.Fprintln(w1, "T1 : ", i)
            }
            wg.Done()
        }
        t2 := func(wg *sync.WaitGroup) {
            for i := 0; i < 100; i++ {
                time.Sleep(time.Microsecond * time.Duration(r1.Intn(100)))
                fmt.Println("T2 : ", i)
            }
            wg.Done()
        }
        wg.Add(2)
        go t1(wg)
        go t2(wg)
        wg.Wait()
    }