func (gi *GeoIP) GetCountry_v6(ip string) (cc string, netmask int) {
	if gi.db == nil {
		return
	}
	gi.mu.Lock()
	defer gi.mu.Unlock()
	cip := C.CString(ip)
	defer C.free(unsafe.Pointer(cip))
	ccountry := C.GeoIP_country_code_by_addr_v6(gi.db, cip)
	if ccountry != nil {
		cc = C.GoString(ccountry)
		netmask = int(C.GeoIP_last_netmask(gi.db))
		return
	}
	return
}
GetCountry_v6 works the same as GetCountry except for IPv6 addresses, be sure to
load a database with IPv6 data to get any results.
package geoip
import "C"
import (
	"fmt"
	"log"
	"os"
	"runtime"
	"sync"
	"unsafe"
)
type GeoIP struct {
	db *C.GeoIP
	mu sync.Mutex
}
func (gi *GeoIP) free() {
	if gi == nil {
		return
	}
	if gi.db == nil {
		gi = nil
		return
	}
	C.GeoIP_delete(gi.db)
	gi = nil
	return
}
func Open(files ...string) (*GeoIP, error) {
	return OpenDb(files, GEOIP_MEMORY_CACHE)
}
func OpenDb(files []string, flag int) (*GeoIP, error) {
	if len(files) == 0 {
		files = []string{
			"/usr/share/GeoIP/GeoIP.dat",        
			"/usr/share/local/GeoIP/GeoIP.dat",  
			"/usr/local/share/GeoIP/GeoIP.dat",  
			"/opt/local/share/GeoIP/GeoIP.dat",  
			"/usr/share/GeoIP/GeoIP.dat",        
		}
	}
	g := &GeoIP{}
	runtime.SetFinalizer(g, (*GeoIP).free)
	var err error
	for _, file := range files {
		if _, err := os.Stat(file); err != nil {
			if os.IsExist(err) {
				log.Println(err)
			}
			continue
		}
		cbase := C.CString(file)
		defer C.free(unsafe.Pointer(cbase))
		g.db, err = C.GeoIP_open(cbase, C.int(flag))
		if g.db != nil && err != nil {
			break
		}
	}
	if err != nil {
		return nil, fmt.Errorf("Error opening GeoIP database (%s): %s", files, err)
	}
	if g.db == nil {
		return nil, fmt.Errorf("Didn't open GeoIP database (%s)", files)
	}
	C.GeoIP_set_charset(g.db, C.GEOIP_CHARSET_UTF8)
	return g, nil
}
func SetCustomDirectory(dir string) {
	cdir := C.CString(dir)
	C.GeoIP_setup_custom_directory(cdir)
}
func OpenTypeFlag(dbType int, flag int) (*GeoIP, error) {
	g := &GeoIP{}
	runtime.SetFinalizer(g, (*GeoIP).free)
	var err error
	g.db, err = C.GeoIP_open_type(C.int(dbType), C.int(flag))
	if err != nil {
		return nil, fmt.Errorf("Error opening GeoIP database (%d): %s", dbType, err)
	}
	if g.db == nil {
		return nil, fmt.Errorf("Didn't open GeoIP database (%d)", dbType)
	}
	C.GeoIP_set_charset(g.db, C.GEOIP_CHARSET_UTF8)
	return g, nil
}
func OpenType(dbType int) (*GeoIP, error) {
	return OpenTypeFlag(dbType, GEOIP_MEMORY_CACHE)
}
func (gi *GeoIP) GetOrg(ip string) string {
	name, _ := gi.GetName(ip)
	return name
}
func (gi *GeoIP) GetName(ip string) (name string, netmask int) {
	if gi.db == nil {
		return
	}
	gi.mu.Lock()
	defer gi.mu.Unlock()
	cip := C.CString(ip)
	defer C.free(unsafe.Pointer(cip))
	cname := C.GeoIP_name_by_addr(gi.db, cip)
	if cname != nil {
		name = C.GoString(cname)
		defer C.free(unsafe.Pointer(cname))
		netmask = int(C.GeoIP_last_netmask(gi.db))
		return
	}
	return
}
type GeoIPRecord struct {
	CountryCode   string
	CountryCode3  string
	CountryName   string
	Region        string
	City          string
	PostalCode    string
	Latitude      float32
	Longitude     float32
	MetroCode     int
	AreaCode      int
	CharSet       int
	ContinentCode string
}
func (gi *GeoIP) GetRecord(ip string) *GeoIPRecord {
	if gi.db == nil {
		return nil
	}
	cip := C.CString(ip)
	defer C.free(unsafe.Pointer(cip))
	gi.mu.Lock()
	record := C.GeoIP_record_by_addr(gi.db, cip)
	gi.mu.Unlock()
	if record == nil {
		return nil
	}
	defer C.GeoIPRecord_delete(record)
	rec := new(GeoIPRecord)
	rec.CountryCode = C.GoString(record.country_code)
	rec.CountryCode3 = C.GoString(record.country_code3)
	rec.CountryName = C.GoString(record.country_name)
	rec.Region = C.GoString(record.region)
	rec.City = C.GoString(record.city)
	rec.PostalCode = C.GoString(record.postal_code)
	rec.Latitude = float32(record.latitude)
	rec.Longitude = float32(record.longitude)
	rec.CharSet = int(record.charset)
	rec.ContinentCode = C.GoString(record.continent_code)
	if gi.db.databaseType != C.GEOIP_CITY_EDITION_REV0 {
		union_int := (*int32)(unsafe.Pointer(&record.anon0))
		rec.MetroCode = int(*union_int)
		rec.AreaCode = int(record.area_code)
	}
	return rec
}
func (gi *GeoIP) GetRegion(ip string) (string, string) {
	if gi.db == nil {
		return "", ""
	}
	cip := C.CString(ip)
	defer C.free(unsafe.Pointer(cip))
	gi.mu.Lock()
	region := C.GeoIP_region_by_addr(gi.db, cip)
	gi.mu.Unlock()
	if region == nil {
		return "", ""
	}
	countryCode := C.GoString(&region.country_code[0])
	regionCode := C.GoString(&region.region[0])
	defer C.free(unsafe.Pointer(region))
	return countryCode, regionCode
}
func GetRegionName(countryCode, regionCode string) string {
	cc := C.CString(countryCode)
	defer C.free(unsafe.Pointer(cc))
	rc := C.CString(regionCode)
	defer C.free(unsafe.Pointer(rc))
	region := C.GeoIP_region_name_by_code(cc, rc)
	if region == nil {
		return ""
	}
	regionName := C.GoString(region)
	return regionName
}
func (gi *GeoIP) GetNameV6(ip string) (name string, netmask int) {
	if gi.db == nil {
		return
	}
	gi.mu.Lock()
	defer gi.mu.Unlock()
	cip := C.CString(ip)
	defer C.free(unsafe.Pointer(cip))
	cname := C.GeoIP_name_by_addr_v6(gi.db, cip)
	if cname != nil {
		name = C.GoString(cname)
		defer C.free(unsafe.Pointer(cname))
		netmask = int(C.GeoIP_last_netmask(gi.db))
		return
	}
	return
}
func (gi *GeoIP) GetCountry(ip string) (cc string, netmask int) {
	if gi.db == nil {
		return
	}
	gi.mu.Lock()
	defer gi.mu.Unlock()
	cip := C.CString(ip)
	defer C.free(unsafe.Pointer(cip))
	ccountry := C.GeoIP_country_code_by_addr(gi.db, cip)
	if ccountry != nil {
		cc = C.GoString(ccountry)
		netmask = int(C.GeoIP_last_netmask(gi.db))
		return
	}
	return
}