Rumah >pembangunan bahagian belakang >Golang >Cara menggunakan bahasa Go untuk membangunkan fungsi julat penghantaran bawa pulang sistem pesanan

Cara menggunakan bahasa Go untuk membangunkan fungsi julat penghantaran bawa pulang sistem pesanan

WBOY
WBOYasal
2023-11-01 10:33:171053semak imbas

Cara menggunakan bahasa Go untuk membangunkan fungsi julat penghantaran bawa pulang sistem pesanan

Dengan perkembangan perniagaan bawa pulang, fungsi julat penghantaran bawa pulang telah menjadi titik fungsi yang sangat penting dalam sistem pesanan bawa pulang. Bagi memenuhi keperluan pengguna, banyak platform penghantaran makanan akan menyediakan fungsi sedemikian. Jadi bagaimana untuk menggunakan bahasa Go untuk membangunkan fungsi julat penghantaran ini? Artikel ini akan memperkenalkan proses ini secara terperinci dan menyediakan contoh kod khusus supaya pembaca dapat lebih memahami dan menguasai pelaksanaan fungsi ini.

  1. Prasyarat

Sebelum memulakan pembangunan, kita perlu terlebih dahulu memahami keperluan dan pelaksanaan fungsi ini. Khususnya:

  • Anda perlu memberikan kawasan poligon, iaitu julat perkhidmatan penghantaran bawa pulang
  • Apabila pengguna memasukkan alamat pada halaman pesanan, ia perlu menilai sama ada ia berada dalam julat perkhidmatan berdasarkan kepada lokasi pengguna, untuk memutuskan sama ada Ambil pesanan.

Untuk melaksanakan fungsi ini, kami perlu menggunakan beberapa alatan dan teknologi:

  • Pertama, kami perlu menggunakan perkhidmatan API peta untuk mendapatkan data julat perkhidmatan yang kami perlukan dan maklumat geografi lokasi pengguna.
  • Kedua, kita perlu menggunakan algoritma poligon, iaitu titik dalam algoritma poligon, untuk menentukan sama ada titik kedudukan berada dalam julat perkhidmatan.
  • Akhir sekali, kita perlu membungkus alatan ini ke dalam perpustakaan kod untuk digunakan dalam sistem pesanan.
  1. Idea Reka Bentuk

Sebelum melaksanakan fungsi ini, kita perlu mentakrifkan beberapa struktur data asas dan antara muka:

  • Kawasan poligon: tatasusunan yang menyimpan maklumat geografi berbilang titik
  • , mengandungi Structure:
  • ; maklumat latitud dan longitud;
  • Permintaan pelanggan: mengandungi maklumat alamat pengguna.

Kemudian, kita boleh melaksanakan fungsi ini mengikut idea reka bentuk berikut:

  • Gunakan perkhidmatan API peta untuk mendapatkan maklumat geografi kawasan poligon dan menyimpan maklumat ini dalam tatasusunan
  • Menghuraikan permintaan pelanggan, Dapatkan maklumat geografi lokasi pelanggan
  • Gunakan algoritma poligon untuk menentukan sama ada lokasi pelanggan berada dalam julat perkhidmatan dan memberikan hasil tindak balas yang sepadan.

Dalam bahasa Go, kami boleh menggunakan perpustakaan go-mapbox untuk mengakses perkhidmatan API peta. Pada masa yang sama, kami juga boleh menggunakan perpustakaan matematik terbina dalam dalam bahasa Go untuk melaksanakan algoritma poligon. Pelaksanaan kod khusus adalah seperti berikut:

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)
}

Di atas ialah contoh kod pelaksanaan bahasa Go asas. Sebelum menjalankan kod ini, anda perlu terlebih dahulu mendapatkan Token Akses daripada latar belakang API peta. Hanya gantikan YOUR_ACCESS_TOKEN dengan Token. Selain itu, anda juga perlu memasukkan koordinat dan parameter berkaitan yang sepadan dalam antara muka pertanyaan poligon yang disediakan oleh API peta. Menjalankan kod di atas, anda boleh mendapatkan nilai Boolean yang mewakili sama ada lokasi koordinat berada dalam julat perkhidmatan. YOUR_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

    Dikapsulkan ke dalam perpustakaan boleh guna semula🎜🎜🎜Kod sampel di atas boleh membantu kami melengkapkan fungsi julat penghantaran bawa pulang sistem pesanan bawa pulang. Walau bagaimanapun, dalam aplikasi sebenar, ciri ini boleh digunakan oleh berbilang halaman atau modul. Untuk mengelakkan masalah menulis kod berulang kali, kita perlu memasukkannya ke dalam perpustakaan yang boleh digunakan semula. Khususnya: 🎜🎜🎜Kita boleh merangkum fungsi InDeliveryArea di atas ke dalam fungsi yang boleh dipanggil dari luar. 🎜🎜Selain itu, kami juga boleh menyemak dan mengesahkan parameter input luaran untuk memastikan keteguhan program. 🎜🎜🎜Sebagai contoh, kita boleh menyusun semula kod dan memisahkan dua operasi mendapatkan poligon dan titik penghakiman dalam poligon, yang juga akan memudahkan pengembangan seterusnya. 🎜🎜Berikut ialah contoh kod yang merangkumkan bahasa Go ke dalam perpustakaan boleh guna semula: 🎜rrreee🎜Di sini kami menggunakan corak kilang untuk mencipta struktur DeliveryArea Seperti yang anda lihat, selain mudah digunakan, anda juga boleh mencari bahawa logik dalaman mereka agak jelas Ini seterusnya menjadikan penyelenggaraan lebih mudah. Berikut ialah contoh kod menggunakan perpustakaan terkapsul di atas: 🎜rrreee🎜 Sebelum menjalankan kod ini, anda perlu meletakkan fail perpustakaan di lokasi yang ditentukan dan menggantikan nama pengguna/repo_deliver_area dalam laluan Import Dan ganti Token Akses API peta dengan YOUR_ACCESS_TOKEN. Output akhir ialah nilai Boolean yang mewakili sama ada lokasi koordinat berada dalam julat perkhidmatan. 🎜

Atas ialah kandungan terperinci Cara menggunakan bahasa Go untuk membangunkan fungsi julat penghantaran bawa pulang sistem pesanan. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn