func (i *inotify) lazyinit() error {
	if atomic.LoadInt32(&i.fd) == invalidDescriptor {
		i.Lock()
		defer i.Unlock()
		if atomic.LoadInt32(&i.fd) == invalidDescriptor {
			fd, err := unix.InotifyInit1(unix.IN_CLOEXEC)
			if err != nil {
				return err
			}
			i.fd = int32(fd)
			if err = i.epollinit(); err != nil {
				_, _ = i.epollclose(), unix.Close(int(fd))  
				i.fd = invalidDescriptor
				return err
			}
			esch := make(chan []*event)
			go i.loop(esch)
			i.wg.Add(consumersCount)
			for n := 0; n < consumersCount; n++ {
				go i.send(esch)
			}
		}
	}
	return nil
}
lazyinit sets up all required file descriptors and starts 1+consumersCount
goroutines. The producer goroutine blocks until file-system notifications
occur. Then, all events are read from system buffer and sent to consumer
goroutines which construct valid notify events. This method uses
Double-Checked Locking optimization.
package notify
import (
	"bytes"
	"errors"
	"path/filepath"
	"runtime"
	"sync"
	"sync/atomic"
	"unsafe"
	"golang.org/x/sys/unix"
)
const eventBufferSize = 64 * (unix.SizeofInotifyEvent + unix.PathMax + 1)
const consumersCount = 2
const invalidDescriptor = -1
type watched struct {
	path string
	mask uint32
}
type inotify struct {
	sync.RWMutex                        
	m            map[int32]*watched     
	fd           int32                  
	pipefd       []int                  
	epfd         int                    
	epes         []unix.EpollEvent      
	buffer       [eventBufferSize]byte  
	wg           sync.WaitGroup         
	c            chan<- EventInfo       
}
func newWatcher(c chan<- EventInfo) watcher {
	i := &inotify{
		m:      make(map[int32]*watched),
		fd:     invalidDescriptor,
		pipefd: []int{invalidDescriptor, invalidDescriptor},
		epfd:   invalidDescriptor,
		epes:   make([]unix.EpollEvent, 0),
		c:      c,
	}
	runtime.SetFinalizer(i, func(i *inotify) {
		i.epollclose()
		if i.fd != invalidDescriptor {
			unix.Close(int(i.fd))
		}
	})
	return i
}
func (i *inotify) Watch(path string, e Event) error {
	return i.watch(path, e)
}
func (i *inotify) Rewatch(path string, _, newevent Event) error {
	return i.watch(path, newevent)
}
func (i *inotify) watch(path string, e Event) (err error) {
	if e&^(All|Event(unix.IN_ALL_EVENTS)) != 0 {
		return errors.New("notify: unknown event")
	}
	if err = i.lazyinit(); err != nil {
		return
	}
	iwd, err := unix.InotifyAddWatch(int(i.fd), path, encode(e))
	if err != nil {
		return
	}
	i.RLock()
	wd := i.m[int32(iwd)]
	i.RUnlock()
	if wd == nil {
		i.Lock()
		if i.m[int32(iwd)] == nil {
			i.m[int32(iwd)] = &watched{path: path, mask: uint32(e)}
		}
		i.Unlock()
	} else {
		i.Lock()
		wd.mask = uint32(e)
		i.Unlock()
	}
	return nil
}