Heim >Backend-Entwicklung >Golang >So verwenden Sie die Go-Sprache, um die Lieferbereichsfunktion zum Mitnehmen des Bestellsystems zu entwickeln

So verwenden Sie die Go-Sprache, um die Lieferbereichsfunktion zum Mitnehmen des Bestellsystems zu entwickeln

WBOY
WBOYOriginal
2023-11-01 10:33:171054Durchsuche

So verwenden Sie die Go-Sprache, um die Lieferbereichsfunktion zum Mitnehmen des Bestellsystems zu entwickeln

Mit der Entwicklung des Take-Away-Geschäfts ist die Funktion „Take-Away-Lieferbereich“ zu einem sehr wichtigen Funktionspunkt im Take-Away-Bestellsystem geworden. Um den Bedürfnissen der Nutzer gerecht zu werden, bieten viele Plattformen für die Lieferung von Lebensmitteln eine solche Funktion an. Wie kann man also die Go-Sprache verwenden, um diese Lieferbereichsfunktion zu entwickeln? In diesem Artikel wird dieser Prozess ausführlich vorgestellt und spezifische Codebeispiele bereitgestellt, damit die Leser die Implementierung dieser Funktion besser verstehen und beherrschen können.

  1. Voraussetzungen

Bevor wir mit der Entwicklung beginnen, müssen wir zunächst die Anforderungen und die Implementierung dieser Funktion verstehen. Konkret:

  • Es ist notwendig, einen Polygonbereich anzugeben, d den Standort des Benutzers und entscheidet so, ob Bestellungen angenommen werden sollen.
  • Um diese Funktion zu implementieren, müssen wir einige Tools und Technologien verwenden:

Zuerst müssen wir einen Karten-API-Dienst verwenden, um die benötigten Servicebereichsdaten und die geografischen Informationen zum Standort des Benutzers zu erhalten.
  • Zweitens müssen wir den Polygonalgorithmus verwenden, also den Punkt innerhalb des Polygonalgorithmus, um zu bestimmen, ob der Positionierungspunkt innerhalb des Servicebereichs liegt.
  • Schließlich müssen wir diese Tools zur Verwendung im Bestellsystem in eine Codebibliothek packen.
Designidee
  1. Bevor wir diese Funktion implementieren, müssen wir einige grundlegende Datenstrukturen und Schnittstellen definieren:

Polygonbereich: ein Array, das die geografischen Informationen mehrerer Punkte speichert.
  • Punkt: eine Struktur, die Folgendes enthält: Informationen zum Breiten- und Längengrad;
  • Client-Anfrage: Enthält Benutzeradressinformationen.
  • Dann können wir diese Funktion gemäß den folgenden Entwurfsideen implementieren:

Verwenden Sie einen Karten-API-Dienst, um die geografischen Informationen des Polygonbereichs abzurufen, und speichern Sie diese Informationen in einem Array.
  • Parsen Sie die Client-Anfrage die geografischen Informationen zum Standort des Kunden;
  • Verwenden Sie einen Polygonalgorithmus, um zu bestimmen, ob der Standort des Kunden innerhalb des Servicebereichs liegt, und geben Sie das entsprechende Antwortergebnis aus.
  • In der Go-Sprache können wir die Go-Mapbox-Bibliothek verwenden, um auf den Karten-API-Dienst zuzugreifen. Gleichzeitig können wir auch die integrierte Mathematikbibliothek in der Go-Sprache verwenden, um Polygonalgorithmen zu implementieren. Die spezifische Code-Implementierung lautet wie folgt:
package main

import (
    "fmt"
    "math"
    
    "github.com/ustroetz/go-mapbox"
)

type Point struct {
    Lat float64
    Lng float64
}

type Polygon []Point

func (p Point) ToCoordinates() *mapbox.Coordinates {
    return &mapbox.Coordinates{
        Longitude: p.Lng,
        Latitude:  p.Lat,
    }
}

func ContainsPointInPolygon(point Point, polygon Polygon) bool {
    intersectCount := 0
    polygonLength := len(polygon)

    if polygonLength < 3 {
        return false
    }

    endPoint := Point{Lat: 9999.0, Lng: point.Lng}

    for i := 0; i < len(polygon); i++ {
        startPoint := polygon[i]
        nextPointIndex := (i + 1) % len(polygon)
        nextPoint := polygon[nextPointIndex]

        if startPoint.Lng == nextPoint.Lng && endPoint.Lng == startPoint.Lng && (point.Lng == startPoint.Lng && (point.Lat > startPoint.Lat) == (point.Lat < endPoint.Lat)) {
            return true
        }

        if point.Lng > math.Min(startPoint.Lng, nextPoint.Lng) && point.Lng <= math.Max(startPoint.Lng, nextPoint.Lng) {
            deltaLat := nextPoint.Lat - startPoint.Lat
            if deltaLat == 0 {
                continue
            }
            intersectLat := startPoint.Lat + (point.Lng-startPoint.Lng)*(nextPoint.Lat-startPoint.Lat)/(nextPoint.Lng-startPoint.Lng)
            if intersectLat == point.Lat {
                return true
            }
            if intersectLat > point.Lat {
                intersectCount++
            }
        }
    }

    return intersectCount%2 != 0
}

func InDeliveryArea(point Point, apiKey string) bool {
    client := mapbox.New(apiKey)

    // 可以使用自己的多边形坐标
    geojson, _, _ := client.MapMatching().GetMapMatching(
        []mapbox.Coordinates{
            *point.ToCoordinates(),
        },
           nil,
    )
    polygon := geojson.Features[0].Geometry.Coordinates[0].([]interface{})
    var polygonArray Polygon
    for _, item := range polygon {
        arr := item.([]interface{})
        p := Point{Lat: arr[1].(float64), Lng: arr[0].(float64)}
        polygonArray = append(polygonArray, p)
    }
    fmt.Println("多边形坐标: ", polygonArray)

    return ContainsPointInPolygon(point, polygonArray)
}

func main() {
    point := Point{
        Lat: 31.146922,
        Lng: 121.362282,
    }

    apiKey := "YOUR_ACCESS_TOKEN"

    result := InDeliveryArea(point, apiKey)

    fmt.Println("坐标是否在配送范围内:", result)
}

Das Obige ist ein grundlegendes Codebeispiel für die Go-Sprachimplementierung. Bevor Sie diesen Code ausführen, müssen Sie zunächst ein Zugriffstoken aus dem Karten-API-Hintergrund abrufen. Ersetzen Sie einfach YOUR_ACCESS_TOKEN durch Token. Darüber hinaus müssen Sie die entsprechenden Koordinaten und zugehörigen Parameter in die von der Karten-API bereitgestellte Polygon-Abfrageschnittstelle eingeben. Wenn Sie den obigen Code ausführen, können Sie einen booleschen Wert erhalten, der angibt, ob die Koordinatenposition innerhalb des Servicebereichs liegt.

    Eingekapselt in eine wiederverwendbare BibliothekYOUR_ACCESS_TOKEN即可。另外,还需要在地图API提供的多边形查询接口中输入对应的坐标和相关参数。运行以上代码,可以得到一个代表坐标所在位置是否在服务范围内的布尔值。

    1. 封装成为可复用库

    上述示例代码可以帮助我们完成外卖点餐系统的外卖配送范围功能。但是,在实际应用中,这个功能可能被多个页面或模块所使用。为了避免重复编写代码的麻烦,我们需要将其封装成为一个可复用的库。具体而言:

  • 我们可以将上述的InDeliveryArea函数封装成为一个可以从外部调用的函数。
  • 另外,我们还可以对外部输入的参数进行检查和校验,以保证程序的健壮性。

例如,我们可以将代码重新组织,把获取多边形和判断点在多边形内两个操作分离,这样也方便后续扩展。

以下是Go语言封装成为可复用库的示例代码:

package delivery

import (
    "fmt"
    "math"
    
    "github.com/ustroetz/go-mapbox"
)

type Point struct {
    Lat float64
    Lng float64
}

type Polygon []Point

type DeliveryArea struct {
    polygon Polygon
    client  *mapbox.Client
}

func NewDeliveryArea(apiKey string, polygonArray []Point) *DeliveryArea {
    client := mapbox.New(apiKey)

    var polygon Polygon
    for _, p := range polygonArray {
        polygon = append(polygon, p)
    }

    return &DeliveryArea{polygon: polygon, client: client}
}

func (p Point) ToCoordinates() *mapbox.Coordinates {
    return &mapbox.Coordinates{
        Longitude: p.Lng,
        Latitude:  p.Lat,
    }
}

func (d *DeliveryArea) containsPoint(point Point) bool {
    intersectCount := 0
    polygonLength := len(d.polygon)

    if polygonLength < 3 {
        return false
    }

    endPoint := Point{Lat: 9999.0, Lng: point.Lng}

    for i := 0; i < len(d.polygon); i++ {
        startPoint := d.polygon[i]
        nextPointIndex := (i + 1) % len(d.polygon)
        nextPoint := d.polygon[nextPointIndex]

        if startPoint.Lng == nextPoint.Lng && endPoint.Lng == startPoint.Lng && (point.Lng == startPoint.Lng && (point.Lat > startPoint.Lat) == (point.Lat < endPoint.Lat)) {
            return true
        }

        if point.Lng > math.Min(startPoint.Lng, nextPoint.Lng) && point.Lng <= math.Max(startPoint.Lng, nextPoint.Lng) {
            deltaLat := nextPoint.Lat - startPoint.Lat
            if deltaLat == 0 {
                continue
            }
            intersectLat := startPoint.Lat + (point.Lng-startPoint.Lng)*(nextPoint.Lat-startPoint.Lat)/(nextPoint.Lng-startPoint.Lng)
            if intersectLat == point.Lat {
                return true
            }
            if intersectLat > point.Lat {
                intersectCount++
            }
        }
    }

    return intersectCount%2 != 0
}

func (d *DeliveryArea) Contains(point Point) bool {
    resp, _, err := d.client.MapMatching().GetMapMatching(
        []mapbox.Coordinates{
            *point.ToCoordinates(),
        },
           nil,
    )
    if err != nil {
        fmt.Printf("MapMatching error: %s
", err)
        return false
    }
    geojson := resp.Features[0].Geometry.Coordinates[0].([]interface{})

    var polygonArray Polygon
    for _, item := range geojson {
        arr := item.([]interface{})
        p := Point{Lat: arr[1].(float64), Lng: arr[0].(float64)}
        polygonArray = append(polygonArray, p)
    }

    return d.containsPoint(point)
}

这里我们使用了工厂模式来创建DeliveryArea结构体,可以看到,除了方便使用外,还可以发现它们的内部逻辑相对清晰,继而更易于维护。如下是一个使用上述封装后库的示例代码:

package main

import (
    "fmt"

    "github.com/username/repo_deliver_area/delivery"
)

func main() {
    polygonArray := []delivery.Point{
        {Lat: 31.23039, Lng: 121.4737},
        {Lat: 31.23886, Lng: 121.50016},
        {Lat: 31.19394, Lng: 121.5276},
        {Lat: 31.18667, Lng: 121.49978},
    }

    apiKey := "YOUR_ACCESS_TOKEN"

    deliveryArea := delivery.NewDeliveryArea(apiKey, polygonArray)

    point := delivery.Point{
        Lat: 31.146922,
        Lng: 121.362282,
    }

    result := deliveryArea.Contains(point)

    fmt.Println(result)
}

在运行这段代码之前,需要先将库文件放置到指定位置,并替换掉Import路径中的username/repo_deliver_area,以及将地图API的Access Token替换掉 YOUR_ACCESS_TOKEN

🎜Der obige Beispielcode kann uns dabei helfen, die Lieferbereichsfunktion zum Mitnehmen des Bestellsystems zum Mitnehmen zu vervollständigen. In tatsächlichen Anwendungen kann diese Funktion jedoch von mehreren Seiten oder Modulen verwendet werden. Um die Mühe des wiederholten Schreibens von Code zu vermeiden, müssen wir ihn in einer wiederverwendbaren Bibliothek kapseln. Konkret: 🎜🎜🎜Wir können die obige InDeliveryArea-Funktion in eine Funktion kapseln, die von außen aufgerufen werden kann. 🎜🎜Darüber hinaus können wir auch externe Eingabeparameter überprüfen und verifizieren, um die Robustheit des Programms sicherzustellen. 🎜🎜🎜Zum Beispiel können wir den Code neu organisieren und die beiden Vorgänge zum Erhalten von Polygonen und Beurteilen von Punkten innerhalb von Polygonen trennen, was auch die spätere Erweiterung erleichtert. 🎜🎜Das Folgende ist ein Beispielcode, der die Go-Sprache in eine wiederverwendbare Bibliothek kapselt: 🎜rrreee🎜Hier verwenden wir das Factory-Muster, um die DeliveryArea-Struktur zu erstellen. Wie Sie sehen, ist es nicht nur bequem zu verwenden, sondern auch dass ihre interne Logik relativ klar ist, was wiederum die Wartung erleichtert. Das Folgende ist ein Beispielcode, der die oben gekapselte Bibliothek verwendet: 🎜rrreee🎜 Bevor Sie diesen Code ausführen, müssen Sie die Bibliotheksdatei am angegebenen Speicherort platzieren und username/repo_deliver_area im Importpfad ersetzen das Zugriffstoken der Karten-API mit YOUR_ACCESS_TOKEN. Die endgültige Ausgabe ist ein boolescher Wert, der angibt, ob die Position der Koordinate innerhalb des Servicebereichs liegt. 🎜

Das obige ist der detaillierte Inhalt vonSo verwenden Sie die Go-Sprache, um die Lieferbereichsfunktion zum Mitnehmen des Bestellsystems zu entwickeln. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn