2017-02-22 81 views
1

我有以下代碼的一部分,它不會將任何數據寫入文件log.txt。我不明白爲什麼?它不應該是同步問題,因爲我在啓動任何去程序之前關閉文件並在每個程序內部打開/關閉文件。Golang:爲什麼下面的代碼片段不寫入文件?

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

回答

1

首先,您需要等待您的頻道清空。在這種情況下,您不需要緩衝通道。使用一個WaitGroup

其次,打開和關閉每個goroutine中的文件,同時忽略錯誤是實際問題。您無需每次打開和關閉文件。打開一次,寫入後同步。

這工作:

包主要

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

還有在this question

+0

是的,我做到了。在創建完成後沒有儘快關閉,並在每個goroutine中使用相同的fileDescriptior來寫入文件。是的 - 在這種情況下,它會在沒有WaitGroup的情況下運行。但是爲什麼它在最初的例子中不起作用 - 在任何通道或goroutine啓動之前,文件都會創建並關閉。我打開/關閉每個goroutine中的文件。但文件仍然是空的。爲什麼? – PARUS

+0

緩衝通道是非阻塞的。你的main()退出速度更快。 – favoretti

2

兩個明顯的缺點一些額外的信息:

  1. 主程序不等待其他goroutines,當主例程返回時,程序終止,就是這樣爲什麼log.txt是空的。 sync.WaitGroup也許有幫助。

  2. msg, ok := <- logCh,ok只有falselogCh被關閉且爲空時。並且您不撥打close(logCh)

+0

但是在任何其他goroutine啓動之前創建並關閉主例程內的文件,並打開和關閉每個主例程內的文件,但是文件鋼是空的。 – PARUS

+0

@PARUS你是什麼意思「我打開和關閉每個主程序中的文件」? 'WriteString'只會在'logCh'接收到消息時執行。但在此之前,主要功能已經結束。 – zzn

+0

>>如果logCh收到消息。但在此之前,主要功能已經結束。對不起,在上面的代碼中,您需要取消註釋以下//fmt.Scanln()和main函數仍然運行。 – PARUS

相關問題