func (f *IPFilter) ToggleCountry(code string, allowed bool) {
	f.mut.Lock()
	f.codes[code] = allowed
	f.mut.Unlock()
}
ToggleCountry alters a specific country setting
package ipfilter
import (
	"io/ioutil"
	"log"
	"net"
	"net/http"
	"sync"
	"github.com/phuslu/iploc"
	"github.com/tomasen/realip"
)
type Options struct {
	AllowedIPs []string
	BlockedIPs []string
	AllowedCountries []string
	BlockedCountries []string
	BlockByDefault bool
	TrustProxy bool
	Logger interface {
		Printf(format string, v ...interface{})
	}
	IPDB         []byte
	IPDBPath     string
	IPDBNoFetch  bool
	IPDBFetchURL string
}
type IPFilter struct {
	opts Options
	mut            sync.RWMutex
	defaultAllowed bool
	ips            map[string]bool
	codes          map[string]bool
	subnets        []*subnet
}
type subnet struct {
	str     string
	ipnet   *net.IPNet
	allowed bool
}
func New(opts Options) *IPFilter {
	if opts.Logger == nil {
		opts.Logger = log.New(ioutil.Discard, "", 0)
	}
	f := &IPFilter{
		opts:           opts,
		ips:            map[string]bool{},
		codes:          map[string]bool{},
		defaultAllowed: !opts.BlockByDefault,
	}
	for _, ip := range opts.BlockedIPs {
		f.BlockIP(ip)
	}
	for _, ip := range opts.AllowedIPs {
		f.AllowIP(ip)
	}
	for _, code := range opts.BlockedCountries {
		f.BlockCountry(code)
	}
	for _, code := range opts.AllowedCountries {
		f.AllowCountry(code)
	}
	return f
}
func (f *IPFilter) printf(format string, args ...interface{}) {
	if l := f.opts.Logger; l != nil {
		l.Printf("[ipfilter] "+format, args...)
	}
}
func (f *IPFilter) AllowIP(ip string) bool {
	return f.ToggleIP(ip, true)
}
func (f *IPFilter) BlockIP(ip string) bool {
	return f.ToggleIP(ip, false)
}
func (f *IPFilter) ToggleIP(str string, allowed bool) bool {
	if ip, net, err := net.ParseCIDR(str); err == nil {
		if n, total := net.Mask.Size(); n == total {
			f.mut.Lock()
			f.ips[ip.String()] = allowed
			f.mut.Unlock()
			return true
		}
		f.mut.Lock()
		found := false
		for _, subnet := range f.subnets {
			if subnet.str == str {
				found = true
				subnet.allowed = allowed
				break
			}
		}
		if !found {
			f.subnets = append(f.subnets, &subnet{
				str:     str,
				ipnet:   net,
				allowed: allowed,
			})
		}
		f.mut.Unlock()
		return true
	}
	if ip := net.ParseIP(str); ip != nil {
		f.mut.Lock()
		f.ips[ip.String()] = allowed
		f.mut.Unlock()
		return true
	}
	return false
}
func (f *IPFilter) AllowCountry(code string) {
	f.ToggleCountry(code, true)
}
func (f *IPFilter) BlockCountry(code string) {
	f.ToggleCountry(code, false)
}