how to repeat shutting down and establish go routine?

时间:2018-04-20 00:41:59

标签: go

every one,I am new to golang.I wanna get the data from log file generated by my application.cuz roll-back mechanism, I met some problem.For instance,my target log file is chats.log,it will be renamed to chats.log.2018xxx and a new chats.log will be created.so my go routine that read log file will fail to work. so I need detect the change and shutdown the previous go routine and then establish the new go routine.

I looked for modules that can help me,and I found

func ExampleNewWatcher(fn string, createnoti chan string, wg sync.WaitGroup) {
    wg.Add(1)
    defer wg.Done()
    watcher, err := fsnotify.NewWatcher()
    if err != nil {
        log.Fatal(err)
    }
    defer watcher.Close()

    done := make(chan bool)
    go func() {
        for {
            select {
            case event := <-watcher.Events:
                if event.Op == fsnotify.Create && event.Name==fn{
                        createnoti <- "has been created"
                }
            case err := <-watcher.Errors:
                log.Println("error:", err)
            }
        }
    }()

    err = watcher.Add("./")
    if err != nil {
        log.Fatal(err)
    }
    <-done
}

I use fsnotify to detech the change,and make sure the event of file is my log file,and then send some message to a channel.

this is my worker go routine:

func tailer(fn string,isfollow bool, outchan chan string, done <-chan interface{},wg sync.WaitGroup) error {
    wg.Add(1)
    defer wg.Done()
    _, err := os.Stat(fn)
    if err != nil{
        panic(err)
    }
    t, err := tail.TailFile(fn, tail.Config{Follow:isfollow})
    if err != nil{
        panic(err)
    }
    defer t.Stop()

    for line := range t.Lines{
        select{
        case outchan <- line.Text:
            case <- done:
                return nil
        }
    }

    return nil
}

I using tail module to read the log file,and I add a done channel to it to shutdown the cycle(I don't know whether I put it in the right way) And I will send every log content to a channel to consuming it. So here is the question:how should I put it together?

ps: Actually,I can use some tool to do this job.like apache-flume,but all of those tools need dependency. Thank you a lot!

1 个答案:

答案 0 :(得分:2)

Here is a complete example that reloads and rereads the file as it changes or gets deleted and recreated:

package main

import (
        "github.com/fsnotify/fsnotify"
        "io/ioutil"
        "log"
)

const filename = "myfile.txt"

func ReadFile(filename string) string {
        data, err := ioutil.ReadFile(filename)
        if err != nil {
                log.Println(err)
        }
        return string(data)
}

func main() {
        watcher, err := fsnotify.NewWatcher()
        if err != nil {
                log.Fatal(err)
        }
        defer watcher.Close()
        err = watcher.Add("./")
        if err != nil {
                log.Fatal(err)
        }
        for {
                select {
                case event := <-watcher.Events:
                        if event.Op == fsnotify.Create && event.Name == filename {
                                log.Println(ReadFile(filename))
                        }
                case err := <-watcher.Errors:
                        log.Println("error:", err)
                }
        }
}

Note this doesn't require goroutines, channels or a WaitGroup. Better to keep things simple and reserve those for when they're actually needed.