PARUS
PARUS

Reputation: 113

Golang: why following code snippet do not write to file?

I have following part of code which do not write any data to file log.txt. I don't understand why ? It should not be sync problem, because I close file before start any go routine and open/close file inside of each routine.

package main

import (
    "fmt"
    "runtime"
    "os"
    "time"
)

func main() {
    runtime.GOMAXPROCS(4)

    f, _ := os.Create("./log.txt")
    f.Close()

    logCh := make(chan string, 50)

    go func() {
        for {
            msg, ok := <- logCh
            if ok {
                logTime := time.Now().Format(time.RFC3339)

                f, _ := os.OpenFile("./log.txt", os.O_APPEND, os.ModeAppend)

                f.WriteString(logTime + " - " + msg)

                f.Close()

            } else {
                break
            }
        }
    }()


    for i:=1; i < 10;i++ {
        for j:=1; j<10;j++ {
            go func(i, j int) {
                msg := fmt.Sprintf("%d + %d = %d\n", i, j, i+j)
                logCh <- msg
                fmt.Print(msg)
            }(i, j)
        }
    }


    //fmt.Scanln()
}

Upvotes: 1

Views: 696

Answers (2)

favoretti
favoretti

Reputation: 30207

For one, you need to wait for your channel to empty. In this case you don't need a buffered channel either. Use a WaitGroup

Secondly, opening and closing the file in every goroutine while ignoring the error is the actual issue. You don't need to open and close the file every time. Open once, sync after writes.

This works:

package main

import (
    "fmt"
    "os"
    "runtime"
    "sync"
    "time"
)

func main() {
    runtime.GOMAXPROCS(4)

    f, _ := os.Create("./log.txt")
    defer f.Close()

    logCh := make(chan string)
    var wg sync.WaitGroup

    for i := 1; i < 10; i++ {
        for j := 1; j < 10; j++ {
            wg.Add(1)
            go func(i, j int) {
                defer wg.Done()
                msg := fmt.Sprintf("%d + %d = %d\n", i, j, i+j)
                logCh <- msg
                fmt.Print(msg)

            }(i, j)
        }
    }

    go func() {
        for {
            msg, ok := <-logCh
            if ok {
                logTime := time.Now().Format(time.RFC3339)

                f.WriteString(logTime + " - " + msg)
                f.Sync()

            } else {
                break
            }
        }
    }()

    wg.Wait()

    //fmt.Scanln()
}

There's also some extra info in this question

Upvotes: 1

zzn
zzn

Reputation: 2465

two obvious faults:

  1. the main routine do not wait for other goroutines, when main routine return, the program terminate, that's why log.txt is empty. sync.WaitGroup maybe helpful.

  2. msg, ok := <- logCh, ok is only false when logCh is closed and empty. And you are not calling close(logCh).

Upvotes: 2

Related Questions