是否可以在 golang 中创建一个包含具有接收器的函数的映射?
我要完成以下任务
函数回调:
func (my *mystruct) doSometing(int parameter1){
// do something
}
func (my *mystruct) doAnotherThing(int parameter1){
// do something
}
包含指向函数的指针的映射
var lookupMap = map[string]func(int){
"action1" : doSomething,
"action2" : doAnotherThing
}
不幸的是,这不起作用,因为回调函数绑定(bind)到接收器。 Go 编译器说:
"undefined doSomething"
我的问题:
创建值是绑定(bind)到特定接收器的函数的映射的语法是什么?
类似于(伪代码):
var lookupMap = map[string]((*mystruct)func(int)){
}
感谢任何帮助!
最佳答案
您可以使用 Method values以此目的。方法值是具有隐式接收者的函数值。引自 Spec: Method values :
If the expression
xhas static typeTandMis in the method set of typeT,x.Mis called a method value.
所以方法值的语法是x.M,例如x是类型的值,M是名称方法。这导致函数具有与没有接收器的方法相同的参数(和返回类型),因为接收器将与方法值一起保存并且是隐式的。
所以这意味着为您的 doSometing() 和 doAnotherThing() 方法存储方法值,函数类型将只是 func (int)(无接收器)。
这是一个工作示例:
type mystruct struct {
name string
}
func (my *mystruct) doA(i int) {
fmt.Printf("[doA]: I'm %s, param is: %d\n", my.name, i)
}
func (my *mystruct) doB(i int) {
fmt.Printf("[doB]: I'm %s, param is: %d\n", my.name, i)
}
func main() {
my1 := &mystruct{"Bob"}
my2 := &mystruct{"Alice"}
lookupMap := map[string]func(int){
"action1": my1.doA,
"action2": my2.doB,
}
lookupMap["action1"](11)
lookupMap["action2"](22)
}
输出(在 Go Playground 上尝试):
[doA]: I'm Bob, param is: 11
[doB]: I'm Alice, param is: 22
如果您不想将接收器保存在字典中(在方法值中),您可以使用 Method expressions .
不同的是,获取函数值时,不是使用x.M,而是使用T.M,会得到一个函数值,函数类型为相同的参数(和返回类型),但接收者类型也将在参数列表中,并且在第一位。参见 Spec: Method expressions 的引述:
If
Mis in the method set of typeT,T.Mis a function that is callable as a regular function with the same arguments asMprefixed by an additional argument that is the receiver of the method.
因此,在您的情况下,要使用的函数类型将如下所示:func(*mystruct, int)
此外,由于不会保存接收者,因此您必须在调用这些函数时提供它。
查看这个工作示例(它是第一个示例的修改):
type mystruct struct {
name string
}
func (my *mystruct) doA(i int) {
fmt.Printf("[doA]: I'm %s, param is: %d\n", my.name, i)
}
func (my *mystruct) doB(i int) {
fmt.Printf("[doB]: I'm %s, param is: %d\n", my.name, i)
}
func main() {
lookupMap := map[string]func(*mystruct, int){
"action1": (*mystruct).doA,
"action2": (*mystruct).doB,
}
my1 := &mystruct{"Bob"}
my2 := &mystruct{"Alice"}
lookupMap["action1"](my1, 11)
lookupMap["action2"](my2, 22)
}
输出相同(在 Go Playground 上尝试):
[doA]: I'm Bob, param is: 11
[doB]: I'm Alice, param is: 22
查看类似问题:
关于dictionary - 具有接收者函数回调的 Map 语法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39936099/
我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..
我脑子里浮现出一些关于一种新编程语言的想法,所以我想我会尝试实现它。一位friend建议我尝试使用Treetop(Rubygem)来创建一个解析器。Treetop的文档很少,我以前从未做过这种事情。我的解析器表现得好像有一个无限循环,但没有堆栈跟踪;事实证明很难追踪到。有人可以指出入门级解析/AST指南的方向吗?我真的需要一些列出规则、常见用法等的东西来使用像Treetop这样的工具。我的语法分析器在GitHub上,以防有人希望帮助我改进它。class{initialize=lambda(name){receiver.name=name}greet=lambda{IO.puts("He
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
所以我在关注Railscast,我注意到在html.erb文件中,ruby代码有一个微弱的背景高亮效果,以区别于其他代码HTML文档。我知道Ryan使用TextMate。我正在使用SublimeText3。我怎样才能达到同样的效果?谢谢! 最佳答案 为SublimeText安装ERB包。假设您安装了SublimeText包管理器*,只需点击cmd+shift+P即可获得命令菜单,然后键入installpackage并选择PackageControl:InstallPackage获取包管理器菜单。在该菜单中,键入ERB并在看到包时选择
我有一个服务模型/表及其注册表。在表单中,我几乎拥有服务的所有字段,但我想在验证服务对象之前自动设置其中一些值。示例:--服务Controller#创建Action:defcreate@service=Service.new@service_form=ServiceFormObject.new(@service)@service_form.validate(params[:service_form_object])and@service_form.saverespond_with(@service_form,location:admin_services_path)end在验证@ser
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我有一些代码在几个不同的位置之一运行:作为具有调试输出的命令行工具,作为不接受任何输出的更大程序的一部分,以及在Rails环境中。有时我需要根据代码的位置对代码进行细微的更改,我意识到以下样式似乎可行:print"Testingnestedfunctionsdefined\n"CLI=trueifCLIdeftest_printprint"CommandLineVersion\n"endelsedeftest_printprint"ReleaseVersion\n"endendtest_print()这导致:TestingnestedfunctionsdefinedCommandLin
我正在阅读SandiMetz的POODR,并且遇到了一个我不太了解的编码原则。这是代码:classBicycleattr_reader:size,:chain,:tire_sizedefinitialize(args={})@size=args[:size]||1@chain=args[:chain]||2@tire_size=args[:tire_size]||3post_initialize(args)endendclassMountainBike此代码将为其各自的属性输出1,2,3,4,5。我不明白的是查找方法。当一辆山地自行车被实例化时,因为它没有自己的initialize方法
在Ruby类中,我重写了三个方法,并且在每个方法中,我基本上做同样的事情:classExampleClassdefconfirmation_required?is_allowed&&superenddefpostpone_email_change?is_allowed&&superenddefreconfirmation_required?is_allowed&&superendend有更简洁的语法吗?如何缩短代码? 最佳答案 如何使用别名?classExampleClassdefconfirmation_required?is_a
我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_