Saya menerapkan router sederhana di Go. Saya dulu memiliki banyak kode yang berlebihan untuk setiap titik akhir yang mengembalikan kesalahan ketika metode yang dipanggil tidak diterapkan untuk titik akhir itu. Saya memfaktorkan ulang dan membuat tipe "dasar" yang menyediakan fungsi default untuk setiap jenis permintaan yang hanya mengembalikan kesalahan yang tidak diterapkan. Sekarang yang harus saya lakukan adalah mengganti fungsi metode tertentu untuk titik akhir tertentu yang ingin saya terapkan. Ini semua menyenangkan dan permainan sampai saya ingin mencari tahu, mengingat variabel titik akhir, metode mana yang telah diganti?

Menghilangkan detail asing, berikut adalah contoh sederhana yang dapat saya pikirkan saat ini:

package main

import (
    "fmt"
)

// Route defines the HTTP method handlers.
type Route interface {
    Get() string
    Post() string
}

// BaseRoute is the "fallback" handlers,
// if those handlers aren't defined later.
type BaseRoute struct{}

func (BaseRoute) Get() string {
    return "base get"
}

func (BaseRoute) Post() string {
    return "base post"
}

// Endpoint holds a route for handling the HTTP request,
// and some other metadata related to that request.
type Endpoint struct {
    BaseRoute
    URI string
}

// myEndpoint is an example endpoint implementation
// which only implements a GET request.
type myEndpoint Endpoint

func (myEndpoint) Get() string {
    return "myEndpoint get"
}

func main() {
    myEndpointInstance := myEndpoint{URI: "/myEndpoint"}
    fmt.Println(myEndpointInstance.URI)
    fmt.Println(myEndpointInstance.Get())
    fmt.Println(myEndpointInstance.Post())
}

Cuplikan ini akan mencetak yang berikut:

/myEndpoint
myEndpoint get
base post

Jadi penggantian fungsi saya berfungsi sebagaimana dimaksud. Sekarang saya bertanya-tanya bahwa dalam fungsi utama saya, setelah saya mendeklarasikan myEndpointInstance, dapatkah saya mengetahui bahwa fungsi Post belum diganti dan masih diimplementasikan oleh BaseRoute yang mendasarinya tanpa benar-benar memanggil fungsi tersebut? Idealnya, saya menginginkan sesuatu seperti ini:

func main() {
    myEndpointInstance := myEndpoint{URI: "/myEndpoint"}
    if myEndpointInstace.Post != BaseRoute.Post {
        // do something
    }
}

Saya telah bermain-main dengan paket refleksi sedikit, tetapi belum menemukan sesuatu yang membantu.

4
WorkForPizza 17 Maret 2019, 08:04

1 menjawab

Jawaban Terbaik

Seperti dicatat oleh orang lain, metode mana yang dipanggil adalah keputusan waktu kompilasi. Jadi Anda dapat memeriksa ini pada waktu kompilasi, sebagian besar IDE akan mengarahkan Anda ke metode yang terikat dengan panggilan sebenarnya.

Jika Anda ingin memeriksa ini saat runtime, Anda dapat membandingkan pointer fungsi. Anda tidak dapat membandingkan nilai fungsi, nilai tersebut tidak dapat dibandingkan (hanya dengan nilai nil). Spesifikasi: Operator perbandingan:

Nilai irisan, peta, dan fungsi tidak dapat dibandingkan. Namun, sebagai kasus khusus, nilai irisan, peta, atau fungsi dapat dibandingkan dengan pengenal nil yang telah dideklarasikan sebelumnya.

Ini adalah bagaimana Anda dapat melakukannya:

myEndpointInstance := myEndpoint{URI: "/myEndpoint"}

v1 := reflect.ValueOf(myEndpointInstance.Post).Pointer()
v2 := reflect.ValueOf(myEndpointInstance.BaseRoute.Post).Pointer()
fmt.Println(v1, v2, v1 == v2)

v1 = reflect.ValueOf(myEndpointInstance.Get).Pointer()
v2 = reflect.ValueOf(myEndpointInstance.BaseRoute.Get).Pointer()
fmt.Println(v1, v2, v1 == v2)

Ini akan menampilkan (coba di Go Playground):

882848 882848 true
882880 882912 false

Output memberitahu Post() tidak "ditimpa" (myEndpointInstance.Post sama dengan myEndpointInstance.BaseRoute.Post), sedangkan Get() adalah (myEndpointInstance.Get tidak sama dengan myEndpointInstance.BaseRoute.Get).

Lihat pertanyaan terkait:

Bagaimana cara membandingkan 2 fungsi di Go?

Kumpulan Fungsi Unik di Go

5
icza 17 Maret 2019, 17:49