如何在Go中重写类型的基本函数,而不调用函数?

问题描述 投票:4回答:1

我在Go中实现了一个简单的路由器。我曾经为每个端点提供了大量冗余代码,当没有为该端点实现调用的方法时返回错误。我重构并创建了一个“基础”类型,它为每个只返回未实现错误的请求类型提供默认函数。现在,我所要做的就是覆盖我希望实现的给定端点的特定方法函数。这是有趣和游戏,直到我想弄清楚,给定一个端点变量,哪些方法已被覆盖?

省略无关的细节,这就像我现在想象的那样简单:

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

此代码段将打印出以下内容:

/myEndpoint
myEndpoint get
base post

所以我的覆盖功能按预期工作。现在我想知道在我的main函数中,在我声明了myEndpointInstance之后,我能否以某种方式告诉Post函数没有被覆盖并且仍然由底层BaseRoute实现而没有实际调用函数?理想情况下,我想要这样的东西:

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

我曾经玩过反射套件,但没有发现任何有用的东西。

function go methods override
1个回答
5
投票

正如其他人所指出的那样,调用哪种方法是编译时决策。因此,您可以在编译时检查这一点,大多数IDE将导航到绑定到实际调用的方法。

如果要在运行时检查此项,可以比较函数指针。您无法比较函数值,它们不具有可比性(仅限于nil值)。 Spec: Comparison operators

切片,贴图和函数值无法比较。然而,作为特殊情况,可以将切片,映射或函数值与预先声明的标识符nil进行比较。

这是你如何做到这一点:

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)

这将输出(在Go Playground上尝试):

882848 882848 true
882880 882912 false

输出告诉Post()不是“被覆盖”(myEndpointInstance.PostmyEndpointInstance.BaseRoute.Post相同),而Get()是(myEndpointInstance.GetmyEndpointInstance.BaseRoute.Get不同)。

查看相关问题:

How to compare 2 functions in Go?

Collection of Unique Functions in Go

© www.soinside.com 2019 - 2024. All rights reserved.