以下是要翻译的内容: 为什么以下代码片段不会将内容写入文件?

huangapple go评论71阅读模式
英文:

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

问题

我有以下一段代码,但它没有将任何数据写入到log.txt文件中。我不明白为什么会这样?这不应该是同步问题,因为我在启动任何go例程之前都关闭了文件,并在每个例程内部打开/关闭文件。

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()
}
英文:

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 (
	&quot;fmt&quot;
	&quot;runtime&quot;
	&quot;os&quot;
	&quot;time&quot;
)

func main() {
	runtime.GOMAXPROCS(4)

	f, _ := os.Create(&quot;./log.txt&quot;)
	f.Close()

	logCh := make(chan string, 50)
	
	go func() {
		for {
			msg, ok := &lt;- logCh
			if ok {
				logTime := time.Now().Format(time.RFC3339)

				f, _ := os.OpenFile(&quot;./log.txt&quot;, os.O_APPEND, os.ModeAppend)

				f.WriteString(logTime + &quot; - &quot; + msg)

				f.Close()

			} else {
				break
			}
		}
	}()


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


	//fmt.Scanln()
}

答案1

得分: 2

两个明显的问题:

  1. 主程序没有等待其他goroutine,当主程序返回时,程序终止,这就是为什么log.txt是空的。可以使用sync.WaitGroup来解决这个问题。

  2. msg, ok := <- logCh,只有当logCh被关闭且为空时,ok才为false。而你没有调用close(logCh)

英文:

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 := &lt;- logCh, ok is only false when logCh is closed and empty. And you are not calling close(logCh).

答案2

得分: 1

首先,你需要等待通道为空。在这种情况下,你也不需要使用缓冲通道。可以使用WaitGroup

其次,每个goroutine中打开和关闭文件并忽略错误是实际的问题。你不需要每次都打开和关闭文件。只需打开一次,写入后进行同步。

以下是修正后的代码:

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()
}

这个问题中还有一些额外的信息。

英文:

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 (
	&quot;fmt&quot;
	&quot;os&quot;
	&quot;runtime&quot;
	&quot;sync&quot;
	&quot;time&quot;
)

func main() {
	runtime.GOMAXPROCS(4)

	f, _ := os.Create(&quot;./log.txt&quot;)
	defer f.Close()

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

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

			}(i, j)
		}
	}

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

				f.WriteString(logTime + &quot; - &quot; + msg)
				f.Sync()

			} else {
				break
			}
		}
	}()

	wg.Wait()

	//fmt.Scanln()
}

There's also some extra info in this question

huangapple
  • 本文由 发表于 2017年2月22日 14:36:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/42384336.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定