github.com/micro/go-micro/examples@v0.0.0-20210105173217-bf4ab679e18b/booking/srv/geo/main.go (about) 1 package main 2 3 import ( 4 "encoding/json" 5 "log" 6 7 "github.com/hailocab/go-geoindex" 8 "github.com/micro/go-micro/examples/booking/data" 9 "github.com/micro/go-micro/examples/booking/srv/geo/proto" 10 11 "context" 12 "golang.org/x/net/trace" 13 14 "github.com/micro/go-micro/v2" 15 "github.com/micro/go-micro/v2/metadata" 16 ) 17 18 const ( 19 maxSearchRadius = 10 20 maxSearchResults = 5 21 ) 22 23 type point struct { 24 Pid string `json:"hotelId"` 25 Plat float64 `json:"lat"` 26 Plon float64 `json:"lon"` 27 } 28 29 // Implement Point interface 30 func (p *point) Lat() float64 { return p.Plat } 31 func (p *point) Lon() float64 { return p.Plon } 32 func (p *point) Id() string { return p.Pid } 33 34 type Geo struct { 35 index *geoindex.ClusteringIndex 36 } 37 38 // Nearby returns all hotels within a given distance. 39 func (s *Geo) Nearby(ctx context.Context, req *geo.Request, rsp *geo.Result) error { 40 md, _ := metadata.FromContext(ctx) 41 traceID := md["traceID"] 42 43 if tr, ok := trace.FromContext(ctx); ok { 44 tr.LazyPrintf("traceID %s", traceID) 45 } 46 47 // create center point for query 48 center := &geoindex.GeoPoint{ 49 Pid: "", 50 Plat: float64(req.Lat), 51 Plon: float64(req.Lon), 52 } 53 54 // find points around center point 55 points := s.index.KNearest(center, maxSearchResults, geoindex.Km(maxSearchRadius), func(p geoindex.Point) bool { 56 return true 57 }) 58 59 for _, p := range points { 60 rsp.HotelIds = append(rsp.HotelIds, p.Id()) 61 } 62 return nil 63 } 64 65 // newGeoIndex returns a geo index with points loaded 66 func newGeoIndex(path string) *geoindex.ClusteringIndex { 67 file := data.MustAsset(path) 68 69 // unmarshal json points 70 var points []*point 71 if err := json.Unmarshal(file, &points); err != nil { 72 log.Fatalf("Failed to load hotels: %v", err) 73 } 74 75 // add points to index 76 index := geoindex.NewClusteringIndex() 77 for _, point := range points { 78 index.Add(point) 79 } 80 return index 81 } 82 83 func main() { 84 service := micro.NewService( 85 micro.Name("go.micro.srv.geo"), 86 ) 87 88 service.Init() 89 90 geo.RegisterGeoHandler(service.Server(), &Geo{ 91 index: newGeoIndex("data/locations.json"), 92 }) 93 94 service.Run() 95 }