This is a creation in Article, where the information may have evolved or changed. Tail is a command that most of us are familiar with. I assume you are also familiar with the '-f ' option provided. If you are unfamiliar, know that it will print out the last few lines of the file. Recently working on a project, I want to know what I need to do to implement this feature. The idea comes from reading [Feynman] (http://amzn.to/2AIWVuX) book:> no doubt, you know how to do it; But when you play this kind of thing like a child, and you don't see the answer ... It's interesting to try to figure out how to do it. Then, when you enter adulthood, you develop certain confidence that you can discover things; But if they have been discovered, then you should not bother yourself at all. What a fool can do, another fool can do, and some other fool to beat you should not disturb you: you should be happy for the things you will find. It may be a trivial thing to implement. But I think it's going to be a good start in a series of articles, and in this article I wrote about how to implement something. So let me show you how to implement the ' tail-f ' process in Go. First, let's get to the point. The tail command provides a flag that can "trace" a file. What it does is wait for any changes to be added to the end of the file and print them out. For the sake of simplicity, I'm not going to implement tail, but just implement the tracking feature. So we print the entire file at the beginning, and then we print the line when we add them. The first thing I think about is the very naïve way of doing this. Prints all the bytes in the file until ' io ' is reached. EOF '; Let the process sleep for a while and then try again. Let's take a look at this function: "' Gofunc follow (file IO. Reader) Error {r: = Bufio. Newreader (file) for {by, err: = R.readbytes (' \ n ') if err! = Nil && Err! = Io. EOF {return err}fmt. Print (String (by)) if Err = = Io. EOF {time. Sleep (time. Second)}}} "when the content is written to the file, it is sadly not responding in a timely manner. Linux provides an API to monitor file system events: INotify APS. The manual page gives you a good introduction. It provides two functions that we are interested in: ' Inotify_init ' and ' Inotify_add_watch '. The ' inotify_init ' function creates an object that we will use to further communicate with the APIMutual. The ' Inotify_add_watch ' function allows you to specify the file events of interest. The API provides several events, but we are concerned with the ' in_modify ' event that is emitted when the file is modified. As we use go, we have to list the ' Syscall ' package. It provides the wrapper for the previously mentioned features: ' Syscall. Inotifyinit ' and ' syscall. Inotifyaddwatch '. Using Syscall let's see how to implement the follow function. For the sake of brevity, I omitted error handling, and when you see a ' _ ' variable being used, it is a good place to handle the return error. "' Gofunc follow (filename string) error {file, _: = OS. Open (filename) fd, _: = Syscall. Inotifyinit () _, _: = Syscall. Inotifyaddwatch (FD, filename, syscall. in_modify) R: = Bufio. Newreader (file) for {by, err: = R.readbytes (' \ n ') if err! = Nil && Err! = Io. EOF {return err}fmt. Print (String (by)) if err! = Io. EOF {Continue}if err = Waitforchange (FD); Err! = Nil {return err}}}func waitforchange (fd int) error {for {var buf [syscall. Sizeofinotifyevent]byte_, _: = Syscall. Read (FD, buf[:]) if err! = Nil {return err}r: = bytes. Newreader (buf[:]) var ev = Syscall. inotifyevent{}_ = binary. Read (r, Binary. Littleendian, &ev) if EV. Mask&syscall. In_modify = = Syscall. in_modify {return nil}} ' Inotifyinit ' function returns a can be used to read ' Sycall. Inotifyevent ' file handlers. From thisHandler reads are a blocking operation. This allows us to respond only when the event is created. If you are dealing with multiple operating systems, it is best to handle the operating system more generally. This is the source of the Fsnotify software package. It provides an abstraction for Linux Inotify,bsd, such as Kqueue. Using fsnotify Our functions look very similar to the previous, but they are much simpler. "' Gofunc follow (filename string) error {file, _: = OS. Open (filename) Watcher, _: = Fsnotify. Newwatcher () Defer watcher. Close () _ = Watcher. ADD (filename) r: = Bufio. Newreader (file) for {by, err: = R.readbytes (' \ n ') if err! = Nil && Err! = Io. EOF {return err}fmt. Print (String (by)) if err! = Io. EOF {Continue}if err = Waitforchange (watcher); Err! = Nil {return Err}}}func waitforchange (w *fsnotify). Watcher) Error {for {select {case event: = <-w.events:if event. Op&fsnotify. Write = = Fsnotify. Write {return nil}case err: = <-w.errors:return Err}} "" I want the code to be interpreted better than the text I wrote. For brevity, I omitted several scenarios in which the code might fail. In order to improve the function, I must dig deep. But it's enough to give me a thirst for knowledge: how it works. I hope you feel the same.
Via:http://satran.in/2017/11/15/implementing_tails_follow_in_go.html
Author: Satyajit Ranjeev Translator: Shniu proofreading: polaris1119
This article by GCTT original compilation, go language Chinese network honor launches
This article was originally translated by GCTT and the Go Language Chinese network. Also want to join the ranks of translators, for open source to do some of their own contribution? Welcome to join Gctt!
Translation work and translations are published only for the purpose of learning and communication, translation work in accordance with the provisions of the CC-BY-NC-SA agreement, if our work has violated your interests, please contact us promptly.
Welcome to the CC-BY-NC-SA agreement, please mark and keep the original/translation link and author/translator information in the text.
The article only represents the author's knowledge and views, if there are different points of view, please line up downstairs to spit groove
294 Reads