func Neighbors(hash string) []string {
	box := BoundingBox(hash)
	lat, lng := box.Center()
	latDelta := box.MaxLat - box.MinLat
	lngDelta := box.MaxLng - box.MinLng
	precision := uint(len(hash))
	return []string{
		EncodeWithPrecision(lat+latDelta, lng, precision),
		EncodeWithPrecision(lat+latDelta, lng+lngDelta, precision),
		EncodeWithPrecision(lat, lng+lngDelta, precision),
		EncodeWithPrecision(lat-latDelta, lng+lngDelta, precision),
		EncodeWithPrecision(lat-latDelta, lng, precision),
		EncodeWithPrecision(lat-latDelta, lng-lngDelta, precision),
		EncodeWithPrecision(lat, lng-lngDelta, precision),
		EncodeWithPrecision(lat+latDelta, lng-lngDelta, precision),
	}
}
Neighbors returns a slice of geohash strings that correspond to the provided
geohash's neighbors.
package geohash
import (
	"errors"
	"fmt"
	"math"
)
type Direction int
const (
	North Direction = iota
	NorthEast
	East
	SouthEast
	South
	SouthWest
	West
	NorthWest
)
func Encode(lat, lng float64) string {
	return EncodeWithPrecision(lat, lng, 12)
}
func EncodeWithPrecision(lat, lng float64, chars uint) string {
	bits := 5 * chars
	inthash := EncodeIntWithPrecision(lat, lng, bits)
	enc := base32encoding.Encode(inthash)
	return enc[12-chars:]
}
func EncodeInt(lat, lng float64) uint64
func encodeInt(lat, lng float64) uint64 {
	latInt := encodeRange(lat, 90)
	lngInt := encodeRange(lng, 180)
	return interleave(latInt, lngInt)
}
func EncodeIntWithPrecision(lat, lng float64, bits uint) uint64 {
	hash := EncodeInt(lat, lng)
	return hash >> (64 - bits)
}
type Box struct {
	MinLat float64
	MaxLat float64
	MinLng float64
	MaxLng float64
}
func (b Box) Center() (lat, lng float64) {
	lat = (b.MinLat + b.MaxLat) / 2.0
	lng = (b.MinLng + b.MaxLng) / 2.0
	return
}
func (b Box) Contains(lat, lng float64) bool {
	return (b.MinLat <= lat && lat <= b.MaxLat &&
		b.MinLng <= lng && lng <= b.MaxLng)
}
func maxDecimalPower(r float64) float64 {
	m := int(math.Floor(math.Log10(r)))
	return math.Pow10(m)
}
func (b Box) Round() (lat, lng float64) {
	x := maxDecimalPower(b.MaxLat - b.MinLat)
	lat = math.Ceil(b.MinLat/x) * x
	x = maxDecimalPower(b.MaxLng - b.MinLng)
	lng = math.Ceil(b.MinLng/x) * x
	return
}
func errorWithPrecision(bits uint) (latErr, lngErr float64) {
	b := int(bits)
	latBits := b / 2
	lngBits := b - latBits
	latErr = math.Ldexp(180.0, -latBits)
	lngErr = math.Ldexp(360.0, -lngBits)
	return
}
func BoundingBox(hash string) Box {
	bits := uint(5 * len(hash))
	inthash := base32encoding.Decode(hash)
	return BoundingBoxIntWithPrecision(inthash, bits)
}
func BoundingBoxIntWithPrecision(hash uint64, bits uint) Box {
	fullHash := hash << (64 - bits)
	latInt, lngInt := deinterleave(fullHash)
	lat := decodeRange(latInt, 90)
	lng := decodeRange(lngInt, 180)
	latErr, lngErr := errorWithPrecision(bits)
	return Box{
		MinLat: lat,
		MaxLat: lat + latErr,
		MinLng: lng,
		MaxLng: lng + lngErr,
	}
}
func BoundingBoxInt(hash uint64) Box {
	return BoundingBoxIntWithPrecision(hash, 64)
}
func Validate(hash string) error {
	if 5*len(hash) > 64 {
		return errors.New("too long")
	}
	for i := 0; i < len(hash); i++ {
		if !base32encoding.ValidByte(hash[i]) {
			return fmt.Errorf("invalid character %q", hash[i])
		}
	}
	return nil
}
func Decode(hash string) (lat, lng float64) {
	box := BoundingBox(hash)
	return box.Round()
}
func DecodeCenter(hash string) (lat, lng float64) {
	box := BoundingBox(hash)
	return box.Center()
}
func DecodeIntWithPrecision(hash uint64, bits uint) (lat, lng float64) {
	box := BoundingBoxIntWithPrecision(hash, bits)
	return box.Round()
}
func DecodeInt(hash uint64) (lat, lng float64) {
	return DecodeIntWithPrecision(hash, 64)
}
func ConvertStringToInt(hash string) (uint64, uint) {
	return base32encoding.Decode(hash), uint(5 * len(hash))
}
func ConvertIntToString(hash uint64, chars uint) string {
	enc := base32encoding.Encode(hash)
	return enc[12-chars:]
}