func New(hostsFName, resolvFName string, logger *dns.Logger) (r *Resolver, err error) {
	if logger == nil {
		logger = dns.NoLogger
	}
	r = &Resolver{cache: cache.New(), log: logger, pendingA: newGoStrMapBool(), pendingAAAA: newGoStrMapBool()}
	defer func() {
		if e := recover(); e != nil {
			if r.log.Level >= dns.LOG_ERRORS {
				r.log.Log("FAIL New: %s", e.(error))
			}
			r = nil
		}
	}()
	if r.log.Level >= dns.LOG_TRACE {
		r.log.Log("New(hosts %q resolv %q)", hostsFName, resolvFName)
	}
	if hostsFName == "" {
		hostsFName = hosts.Sys
	}
	r.hostName, err = os.Hostname()
	if err != nil {
		panic(err)
	}
	var hostsCfg *hosts.Cfg
	hostsCfg, err = hosts.NewCfg(hostsFName, logger)
	if err != nil {
		panic(err)
	}
	if resolvFName == "" {
		resolvFName = resolv.Sys
	}
	var resolvCfg *resolv.Cfg
	resolvCfg, err = resolv.NewCfg(resolvFName, logger)
	if err != nil {
		panic(err)
	}
	hostsCfg.SetChanged()
	resolvCfg.SetChanged()
	r.getQueryConf = func() *queryConf {  
		v := &queryConf{Resolver: r}
		hfile, _, herr := hostsCfg.File()
		if herr != nil {
			if r.log.Level >= dns.LOG_ERRORS {
				r.log.Log("FAIL hostsCfg.File: %s", herr)
			}
		}
		if err := v.hostsChanged(hfile); err != nil {
			if r.log.Level >= dns.LOG_ERRORS {
				r.log.Log("FAIL hostsChanged: %s", err)
			}
		}
		cfile, _, cerr := resolvCfg.Conf()
		if cerr != nil {
			if r.log.Level >= dns.LOG_ERRORS {
				r.log.Log("FAIL resolvCfg.File: %s", cerr)
			}
		}
		v.Conf = cfile
		return v
	}
	if r.log.Level >= dns.LOG_TRACE {
		r.log.Log("New() OK")
	}
	return
}
New returns a new Resolver or an error if any.

'hostsFName' is like "/etc/hosts" and may be empty in which case hosts.Sys()
will be used.

'resolvFName' is like "/etc/resolv.conf" and may again be empty in which
case resolv.Sys() is used.

'logger' may be nil.
package resolver
import (
	"encoding/hex"
	"fmt"
	"github.com/cznic/dns"
	"github.com/cznic/dns/cache"
	"github.com/cznic/dns/hosts"
	"github.com/cznic/dns/msg"
	"github.com/cznic/dns/resolv"
	"github.com/cznic/dns/rr"
	"log"
	"net"
	"os"
	"sort"
	"strings"
	"sync"
	"time"
)
type queryConf struct {
	hosts map[string][]net.IP
	ips   map[string][]string
	*resolv.Conf
	*Resolver
}
func (q *queryConf) hostsChanged(f *hosts.File) (err error) {
	q.hosts = map[string][]net.IP{}
	q.ips = map[string][]string{}
	add := func(name string, ip net.IP) {
		q.hosts[name] = append(q.hosts[name], ip)
	}
	for _, item := range *f {
		name := strings.ToLower(item.CanonicalName)
		ip := item.IP
		sip := string([]byte(ip))
		if _, ok := q.ips[sip]; ok {
			return fmt.Errorf("duplicate ip entry %q", ip.String())
		}
		q.ips[sip] = append(append([]string{}, name), item.Aliases...)
		add(strings.ToLower(item.CanonicalName), ip)
		for _, name := range item.Aliases {
			add(strings.ToLower(name), ip)
		}
	}
	return
}
func (q *queryConf) qhosts(name string) (y []net.IP, ok bool) {
	y, ok = q.hosts[name]
	return
}
func (q *queryConf) qips(ip net.IP) (y []string, ok bool) {
	y, ok = q.ips[string([]byte(ip))]
	return
}
func (q *queryConf) hostqlist(name string) (list []string) {
	labels, err := dns.Labels(name)
	if err != nil {
		if q.Resolver.log.Level >= dns.LOG_ERRORS {
			q.Resolver.log.Log("FAIL %s: %s", name, err)
		}
		return
	}
	dots := len(labels) - 1
	ndots := int(q.Conf.Opt.Ndots)
	domain := q.Conf.Domain
	if domain == "" {
		domain = dns.Host2domain(q.Resolver.hostName)
	}
	rooted := dns.IsRooted(name)
	if rooted || dots >= ndots {
		list = append(list, name)  
	}
	if !rooted && dots < ndots {
		rname := dns.RootedName(name)
		if domain != "" {
			list = append(list, rname+domain)
		}
		list = append(list, name)
		for _, s := range q.Conf.Search {
			list = append(list, rname+s)
		}
	}
	return
}
type goStrMapBool struct {
	m    map[string]bool
	lock sync.Mutex
}
func newGoStrMapBool() *goStrMapBool {
	return &goStrMapBool{m: map[string]bool{}}
}
type LookupResult int
const (
	LookupOK           LookupResult = iota  
	LookupAliased                           
	LookupNameError                         
	LookupDataNotFound                      
	LookupFail                              
	LookupAliasLoop                         
	LookupAliasError                        
)
var LookupResultStr = map[LookupResult]string{
	LookupOK:           "Sucess",
	LookupAliased:      "Sucess. QNAME is an alias and the result is for its canonical name",
	LookupNameError:    "QNAME doesn't exist",
	LookupDataNotFound: "QNAME does exist, but no data for the combination of QTYPE and QCLASS were found",
	LookupFail:         "Lookup fail. Could be also wrong resolver configuration or network communication error.",
	LookupAliasLoop:    "Detected a cycle in the aliases chain",
	LookupAliasError:   "QNAME is an alias to a non existing canonical name",
}
type Resolver struct {
	cache                 *cache.Cache
	hostName              string
	log                   *dns.Logger
	getQueryConf          func() *queryConf
	pendingA, pendingAAAA *goStrMapBool  
}