func (r *RegexpList) update() {
	if !r.ConfList.update() {
		return
	}
	r.mutex.Lock()
	defer r.mutex.Unlock()
	r.regs = r.regs[:0]
	for i, line := range r.ConfList.data {
		reg := regexp.MustCompile(`\\u([0-9a-fA-F]+)`)
		line = reg.ReplaceAllStringFunc(line, func(l string) string {
			m := reg.FindStringSubmatch(l)
			code, err := strconv.ParseInt(m[1], 16, 64)
			if err != nil {
				fmt.Println(err)
				return ""
			}
			return fmt.Sprintf("%c", code)
		})
		re, err := regexp.Compile(line)
		if err != nil {
			log.Println("cannot compile regexp", line, "line", i)
		} else {
			r.regs = append(r.regs, re)
		}
	}
}
update read the file and regexp.comples each lines in the file if file is newer.
package util
import (
	"fmt"
	"log"
	"os"
	"regexp"
	"strconv"
	"strings"
	"sync"
	"time"
)
type ConfList struct {
	mtime *time.Time
	path  string
	data  []string
	mutex sync.RWMutex
}
func NewConfList(path string, defaultList []string) *ConfList {
	r := &ConfList{
		path: path,
	}
	r.update()
	if len(r.data) == 0 {
		r.data = defaultList
	}
	return r
}
func (r *ConfList) GetData() []string {
	r.mutex.RLock()
	defer r.mutex.RUnlock()
	d := make([]string, len(r.data))
	copy(d, r.data)
	return d
}
func (r *ConfList) update() bool {
	r.mutex.Lock()
	defer r.mutex.Unlock()
	if r.path == "" {
		return false
	}
	s, err := os.Stat(r.path)
	if err != nil {
		r.data = nil
		return false
	}
	mtime := s.ModTime()
	if r.mtime != nil && !mtime.After(*r.mtime) {
		return false
	}
	r.mtime = &mtime
	r.data = r.data[:0]
	err = EachLine(r.path, func(line string, i int) error {
		if line != "" && !strings.HasPrefix(line, "#") {
			r.data = append(r.data, line)
		}
		return nil
	})
	if err != nil {
		log.Fatal(err)
	}
	return true
}
type RegexpList struct {
	*ConfList
	regs []*regexp.Regexp
}
func NewRegexpList(path string) *RegexpList {
	c := &ConfList{
		path: path,
	}
	r := &RegexpList{
		ConfList: c,
	}
	r.update()
	return r
}
func (r *RegexpList) Check(target string) bool {
	r.update()
	r.mutex.RLock()
	defer r.mutex.RUnlock()
	for _, re := range r.regs {
		if re.MatchString(target) {
			return true
		}
	}
	return false
}