jjzjj

function - 这个Go函数类型 "HandlerFunc"是怎么工作的,来自标准库 "net/http"

coder 2023-06-26 原文

我对 this bit of code from the HTTP package 感到困惑:

type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}

为什么 ServeHTTP 方法具有与其类型完全相同的签名 - 这有什么意义?

测试,我发现如果我传递一个随机函数(foo)给HandlerFunc:

var bar = HandlerFunc(foo)

bar 成为 HandlerFunc 的一个实例,foo 作为它的 ServeHTTP 方法。现在我真的很困惑这到底是怎么回事。

如果我在一个类型上有多个方法,我如何知道哪个方法将附加到新实例以及使用什么名称或顺序?

最佳答案

这种方法允许您在需要 Handler 的上下文中使用函数。

发生的事情是,有一个 Handler 接口(interface):

    type Handler interface {
        ServeHTTP(ResponseWriter, *Request)
    }

并且各种函数被声明为接受被声明为属于该接口(interface)的参数——例如:

    func TimeoutHandler(h Handler, ns int64, msg string) Handler {
        f := func() <-chan int64 {
            return time.After(ns)
        }
        return &timeoutHandler{h, f, msg}
    }

这意味着当你调用这样一个函数时,你必须传入一个属于满足这个接口(interface)的类型的对象,也就是说,一个具有ServeHTTP 具有适当签名的方法。 (在 Go 中,与某些语言不同,类型不需要显式实现接口(interface),它只需要具有接口(interface)指定的方法即可。)

因此,您引用的代码片段:

type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
    f(w, r)
}

创建一个基于 func(ResponseWriter, *Request)HandlerFunc 类型,但是使用名为 ServeHTTP 的方法扩充该类型适当的签名,使其满足 Handler 接口(interface)。此 ServeHTTP 方法只是调用函数本身。所以,如果 f 是一个具有正确签名的函数,你可以这样写:

var h HandlerFunc = f    // h == f, but converted to a HandlerFunc
                         // so it satisfies the Handler interface.
TimeoutHandler(h, 1000000, "timed out")

澄清一些关于此的事情:

Testing, I discovered that if I pass a random function (foo) to the HandlerFunc:

var bar = HandlerFunc(foo)

bar becomes an instance of HandlerFunc with foo as its ServeHTTP method. Now I'm really confused about how on earth this works.

首先,更正确的说法是您已转换一个随机函数 foo 键入 HandlerFunc ,而不是你将函数传递给HandlerFunc,就像HandlerFunc是一个函数一样。 (HandlerFunc(foo) 表示法是类型转换;您也可以编写 var bar HandlerFunc = foo 并让转换隐式发生。)

其次,更正确的说法是 bar 有一个 ServeHTTP 方法 invokes foo,而不是foo 本身实际上 ServeHTTP 方法。

这有意义吗?

关于function - 这个Go函数类型 "HandlerFunc"是怎么工作的,来自标准库 "net/http",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8690900/

有关function - 这个Go函数类型 "HandlerFunc"是怎么工作的,来自标准库 "net/http"的更多相关文章

  1. ruby-on-rails - Ruby net/ldap 模块中的内存泄漏 - 2

    作为我的Rails应用程序的一部分,我编写了一个小导入程序,它从我们的LDAP系统中吸取数据并将其塞入一个用户表中。不幸的是,与LDAP相关的代码在遍历我们的32K用户时泄漏了大量内存,我一直无法弄清楚如何解决这个问题。这个问题似乎在某种程度上与LDAP库有关,因为当我删除对LDAP内容的调用时,内存使用情况会很好地稳定下来。此外,不断增加的对象是Net::BER::BerIdentifiedString和Net::BER::BerIdentifiedArray,它们都是LDAP库的一部分。当我运行导入时,内存使用量最终达到超过1GB的峰值。如果问题存在,我需要找到一些方法来更正我的代

  2. ruby-on-rails - rails : "missing partial" when calling 'render' in RSpec test - 2

    我正在尝试测试是否存在表单。我是Rails新手。我的new.html.erb_spec.rb文件的内容是:require'spec_helper'describe"messages/new.html.erb"doit"shouldrendertheform"dorender'/messages/new.html.erb'reponse.shouldhave_form_putting_to(@message)with_submit_buttonendendView本身,new.html.erb,有代码:当我运行rspec时,它失败了:1)messages/new.html.erbshou

  3. ruby-on-rails - 由于 "wkhtmltopdf",PDFKIT 显然无法正常工作 - 2

    我在从html页面生成PDF时遇到问题。我正在使用PDFkit。在安装它的过程中,我注意到我需要wkhtmltopdf。所以我也安装了它。我做了PDFkit的文档所说的一切......现在我在尝试加载PDF时遇到了这个错误。这里是错误:commandfailed:"/usr/local/bin/wkhtmltopdf""--margin-right""0.75in""--page-size""Letter""--margin-top""0.75in""--margin-bottom""0.75in""--encoding""UTF-8""--margin-left""0.75in""-

  4. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  5. ruby - 如何模拟 Net::HTTP::Post? - 2

    是的,我知道最好使用webmock,但我想知道如何在RSpec中模拟此方法:defmethod_to_testurl=URI.parseurireq=Net::HTTP::Post.newurl.pathres=Net::HTTP.start(url.host,url.port)do|http|http.requestreq,foo:1endresend这是RSpec:let(:uri){'http://example.com'}specify'HTTPcall'dohttp=mock:httpNet::HTTP.stub!(:start).and_yieldhttphttp.shou

  6. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  7. ruby - Infinity 和 NaN 的类型是什么? - 2

    我可以得到Infinity和NaNn=9.0/0#=>Infinityn.class#=>Floatm=0/0.0#=>NaNm.class#=>Float但是当我想直接访问Infinity或NaN时:Infinity#=>uninitializedconstantInfinity(NameError)NaN#=>uninitializedconstantNaN(NameError)什么是Infinity和NaN?它们是对象、关键字还是其他东西? 最佳答案 您看到打印为Infinity和NaN的只是Float类的两个特殊实例的字符串

  8. ruby - 检查方法参数的类型 - 2

    我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)

  9. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  10. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

随机推荐