func (g *Geo) Init(logger *zap.Logger, cfg map[string]string) {
	var err error
	g.level = str2Level[strings.ToLower(cfg["level"])]
	if err := g.validate(cfg); err != nil {
		logger.Fatal("maxmind", zap.Error(err))
	}
	if g.level != LevelASN {
		g.cityDB, err = maxminddb.Open(cfg["path-city"])
		if err != nil {
			logger.Fatal("maxmind", zap.Error(err))
		}
	}
	if g.level%2 == 1 {
		g.isASN = true
		g.asnDB, err = geoip2.Open(cfg["path-asn"])
		if err != nil {
			logger.Fatal("maxmind", zap.Error(err))
		}
	}
	g.fn = g.getFunc()
	g.logger = logger
	logger.Info("geo", zap.String("msg", "maxmind has been initialized"))
}
Init initializes MaxMind database
package maxmind
import (
	"errors"
	"fmt"
	"net"
	"strconv"
	"strings"
	"github.com/oschwald/geoip2-golang"
	"github.com/oschwald/maxminddb-golang"
	"go.uber.org/zap"
)
const (
	LevelASN = iota + 1
	LevelCity
	LevelCityASN
	LevelCityLoc
	LevelCityLocASN
)
type cityRecord struct {
	Country struct {
		ISOCode string            `maxminddb:"iso_code"`
		Names   map[string]string `maxminddb:"names"`
	} `maxminddb:"country"`
	City struct {
		Names map[string]string `maxminddb:"names"`
	} `maxminddb:"city"`
	Subdivisions []struct {
		IsoCode string            `maxminddb:"iso_code"`
		Names   map[string]string `maxminddb:"names"`
	} `maxminddb:"subdivisions"`
}
type cityLocRecord struct {
	Country struct {
		ISOCode string            `maxminddb:"iso_code"`
		Names   map[string]string `maxminddb:"names"`
	} `maxminddb:"country"`
	City struct {
		Names map[string]string `maxminddb:"names"`
	} `maxminddb:"city"`
	Subdivisions []struct {
		IsoCode string            `maxminddb:"iso_code"`
		Names   map[string]string `maxminddb:"names"`
	} `maxminddb:"subdivisions"`
	Location struct {
		AccuracyRadius uint16  `maxminddb:"accuracy_radius"`
		Latitude       float64 `maxminddb:"latitude"`
		Longitude      float64 `maxminddb:"longitude"`
		MetroCode      uint    `maxminddb:"metro_code"`
		TimeZone       string  `maxminddb:"time_zone"`
	} `maxminddb:"location"`
}
type Geo struct {
	logger *zap.Logger
	cityDB *maxminddb.Reader
	asnDB  *geoip2.Reader
	fn     func(string) map[string]string
	level  int
	isASN  bool
}
var str2Level = map[string]int{
	"asn":          LevelASN,
	"city":         LevelCity,
	"city-asn":     LevelCityASN,
	"city-loc":     LevelCityLoc,
	"city-loc-asn": LevelCityLocASN,
}
func New() *Geo {
	return &Geo{}
}