1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
| package city
import ( "encoding/csv" "math" "os" "strconv" )
var ( radius = float64(6371000) rad = math.Pi / 180.0 )
type info struct { name string lng float64 lat float64 }
type Manager struct { citys map[string]*info }
func NewCityConfig(file string) (c *Manager, err error) { c = &Manager{} c.citys, err = c.parseCityInfo(file) if err != nil { return }
return }
func (c *Manager) GetDistance(city1 string, city2 string) (dist float64, err error) { c1 := c.citys[city1] c2 := c.citys[city2] if c1 == nil || c2 == nil { return 0.0, nil }
dist = c.earthDistance(c1, c2)
return }
func (c *Manager) earthDistance(city1 *info, city2 *info) float64 { lng1 := city1.lng * rad lat1 := city1.lat * rad lng2 := city2.lng * rad lat2 := city2.lat * rad theta := lng2 - lng1 dist := math.Acos(math.Sin(lat1)*math.Sin(lat2) + math.Cos(lat1)*math.Cos(lat2)*math.Cos(theta)) return dist * radius }
func (c *Manager) parseCityInfo(filepath string) (locations map[string]*info, err error) { f, err := os.Open(filepath) if err != nil { return nil, err } defer f.Close()
reader := csv.NewReader(f) record, err := reader.ReadAll() if err != nil { return nil, err }
locations = make(map[string]*info, 0) for _, a := range record { city := &info{name: a[0]} lng, err := strconv.ParseFloat(a[1], 64) if err == nil { city.lng = lng } lat, err := strconv.ParseFloat(a[2], 64) if err == nil { city.lat = lat } locations[city.name] = city }
return locations, nil }
|