登录
首页 >  Golang >  Go问答

使用 Golang 实现函数的动态调用

来源:stackoverflow

时间:2024-03-18 13:45:29 233浏览 收藏

在 Go 中实现函数的动态调用是一项常见的任务,但对于初学者来说可能具有挑战性。传统方法是编写测试文件中的模拟函数,但这会引入代码重复和维护问题。本文探讨了一种替代方法,使用 monkeypatching 拦截函数调用并在运行时替换它们,从而实现更灵活和测试友好的解决方案。

问题内容

我对 go 还很陌生,并且仍在学习 go 中的工作原理,因此,话虽如此,我在过去几周一直在研究 go 测试方法以及模拟如何工作,以及我所了解的大部分信息。根据具体功能找到。

例如everything is a function 要么作为接收器或参数传递,但是,我面临的问题是我的函数使用 switch case 来确定应该调用哪个函数,因此它不是从外部传递的。

func (n *notification) notify(m message) error {
    switch n.service {
    case "slack":
        var s slack.slack
        s.user = m.user
        s.host = m.host
        s.provider = m.provider
        s.systemuser = m.systemuser
        return s.slacksend(n.url)
    default:
        return errors.new(codes.code5)
    }
}

上面的代码是我想要测试的函数的样子,我很难弄清楚如何模拟 slacksend() 函数。

我遇到过一些文章说我应该在测试文件中编写函数,当我对函数的功能感到满意时,我应该编写真正的代码。这对我来说听起来不对,因为对我来说,感觉就像我在两个地方有相同的代码,而测试只使用测试中的代码,我可以更改真实的代码并在睾丸检测不到的情况下破坏它。

我主要从事python工作,我习惯使用mock/magicmock之类的东西,它们可以拦截函数调用并在运行时替换,所以如果我不太明白go的tdd方法,请提前道歉。 p>

如果有人想知道,这就是测试代码的样子:

type MockSlack struct {
    *slack.Slack
}

func (s *MockSlack) SlackSend(url string) error {
    if url != "" {
        return nil
    } else {
        return errors.New("url empty")
    }
}

func TestNotify(t *testing.T) {
    m := Message{}
    n := Notification{
        Service: "slack",
        Url:     "https://dummy.io",
    }

    if err := n.Notify(m); err != nil {
        t.Errorf("SlackSend, expected: %s, got: %s", "nil", err.Error())
    }
}

显然 mockslack 结构没有生效,因为它没有真正传入任何地方。

如果有人对我如何嘲笑这个或我应该做什么有任何建议,我将不胜感激。

提前致谢。

更新: 背景

这不是某种网络服务器/应用程序。它是一个 ssh 身份验证插件,因此它是一个服务器端应用程序。至于notify方法,它服务于映射器的目的。因此它可以调用 slack、ms teams、aws sns,这些为调用者提供了较少的处理条件,并且通知的发送方式和位置由 notify 方法决定。


解决方案


如果您无法更改 notify 方法以使其测试友好。一种选择是考虑使用 monkeypatching。这是为 *net.dialer 提供的 example

func main() {
    var d *net.Dialer // Has to be a pointer to because `Dial` has a pointer receiver
    monkey.PatchInstanceMethod(reflect.TypeOf(d), "Dial", func(_ *net.Dialer, _, _ string) (net.Conn, error) {
        return nil, fmt.Errorf("no dialing allowed")
    })
    _, err := http.Get("http://google.com")
    fmt.Println(err) // Get http://google.com: no dialing allowed
}

警告:在测试环境之外使用它是不安全的。

今天关于《使用 Golang 实现函数的动态调用》的内容介绍就到此结束,如果有什么疑问或者建议,可以在golang学习网公众号下多多回复交流;文中若有不正之处,也希望回复留言以告知!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>