给定以下类型:
type A struct {
...
}
func (a *A) Process() {
...
}
我想将A
类型的方法Process
传递给另一个函数,并能够访问A
的底层示例的内容。
我应该如何将这个方法传递给另一个函数?通过指针?以及它应该如何被调用?Process()
方法不会修改A
的示例,我在方法接收器上使用了一个指针,因为结构体相当大。我的问题背后的想法是避免在结构体外部声明函数Process()
,并向其传递大量参数(而是访问结构体的成员)。
3条答案
按热度按时间zynd9foi1#
您甚至可以直接执行此操作,而无需界面:
输出量:
操场上:https://play.golang.org/p/V-q2_zwX8h
rsaldnfx2#
另一个选择是将
func
定义为类型:然后在调用其他函数时将其用作参数:
需要记住的一点是,这些定义是完全相同的:
func (a *A) Process() { a.MyVar }
func Process(a *A) { a.MyVar }
指针接收器就是一个函数,它的局部变量是指向结构体的指针,而值接收器就是一个函数,它的局部变量是指向结构体的值副本。
为什么不使用结构体上的方法,比如选项1呢?原因有很多。将相关方法组合到结构体本身上,比如选项1,看起来确实很直观(特别是来自其他OOP语言,如Java或.NET,在这些语言中,您通常会在单个结构体上添加1000个方法)。但是,由于您指出
struct
本身非常大,这闻起来有SoC
的味道(它太大了),可能需要分解。就我个人而言,我在使用上述选项2时遵循的规则是:
func
没有使用整个结构体的属性(例如,它只对数据的子集进行操作,甚至根本没有操作),我将使用选项2和指针。(或者,使用接口本身和零字节结构体)这使得单元测试变得更加容易,因为它分解了我的结构,正如你所说的那样,它“相当大”,允许我只模拟支持该方法所需的功能的接口。
现在,函数定义本身就是类型。到目前为止,我们有这样的类型:
这可以用作另一个方法的输入,如您所要求的,如下所示:
但对我来说,这让事情有点难以阅读更不用说脆性-有人可以改变那里的函数定义,并打破其他地方的其他东西。
这是我喜欢定义类型的地方:
这样我就可以像这样吃了
这允许你访问
p
作为你指向函数的指针,你可以随意传递。(注意,你不必访问p
的实际指针。IOW,不要这样做&p
,因为func
类型在Golang中是通过引用传递的,就像slices
和maps
一样。)总的来说,当您希望将逻辑分解为更小的可管理(和更易测试)部分时,通常会遵循这种模式--通过使用更小的、更易管理的
AnotherFunc()
方法来导出和单元测试API协定,同时隐藏其内部。工作示例
http://play.golang.org/p/RAJ2t0nWEc
单元测试
将函数类型的概念提升到另一个层次,可以简化单元测试。
可以为
Process()
函数定义全局变量:它将继续以完全相同的方式使用:
现在的区别是在单元测试期间,您可以覆盖函数:
当我接触到一个现有的代码库时,我开始实现一些技巧,以帮助将应用程序与其自身分离-并允许进行更多的测试。
oyxsuwqo3#
您可以使用以下界面实现此目的: