在golang中将对象从一个包传递到下一个包

来自 github,https://github.com/CyCoreSystems/ari/blob/master/_examples/stasisStart/main.go


我正在查看下面的启动和对象被保存到 cl 并稍后用于创建 handlefun .. 所有在同一个主体中.. 如果我想打破它并将 handlefunc 放在另一个包中,我怎样才能将 cl 传递给它?


cl, err := native.Connect(&native.Options{

        Application:  "test",

        Username:     "asterisk",

        Password:     "abc123",

        URL:          "http://localhost:8088/ari",

        WebsocketURL: "ws://localhost:8088/ari/events",

    })

后来,这通过


http.Handle("/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

        // make call

        log.Info("Make sample call")

        h, err := createCall(cl)

        if err != nil {

            log.Error("Failed to create call", "error", err)

            w.WriteHeader(http.StatusBadGateway)

            w.Write([]byte("Failed to create call: " + err.Error()))

            return

        }


        w.WriteHeader(http.StatusOK)

        w.Write([]byte(h.ID()))

    }))


互换的青春
浏览 92回答 2
2回答

噜噜哒

如何cl“传递给”处理函数啊,好的,我将做一个纯粹的猜测,并建议您被一小段代码中混合的太多概念所绊倒。对此的第二个论点http.Handle()是所谓的“函数文字”——“当场”定义函数,而不是“以正常方式”定义它func some_name(list_of_args) body。Go 中的函数字面量是“闭包”,这意味着它们从可用的外部词法范围“捕获”任何变量,它们的主体通过它们的名称来引用它们。您的示例中的函数文字引用cl了该变量,因此它“关闭”了该变量。我们可以“解包”该代码以使其看起来更容易理解:cl, err := native.Connect(...)handler := func(w http.ResponseWriter, r *http.Request) {  h, err := createCall(cl)  ...}http.Handle("/", http.HandlerFunc(handler))现在看起来更明智了吗?分配给变量handler的任何内容都是关闭变量的函数值cl。你能做些什么呢?我们可以尝试将其重写为更简单:cl, err := native.Connect(...)func handler(w http.ResponseWriter, r *http.Request) {  h, err := createCall(cl) // Oops, this won't compile  ...}http.Handle("/", http.HandlerFunc(handler))但是这段代码不会编译,因为常规函数不能引用包含函数定义的词法范围中的变量(让我们不要离题)。那么,你能做些什么呢?您不能只是将另一个参数添加到参数列表中,handle因为它必须具有特定的签名,但是让我们想一想,当您希望函数对附加net/http.HandlerFunc的某个状态进行操作时,您通常会做什么? 对,您将函数转换为某种数据类型的方法。所以,让我们这样做:type myHander struct {  cl native.Client // I have no idea which type native.Connect returns...}func (*mh myHandler) handle(w http.ResponseWriter, r *http.Request) {  h, err := createCall(mh.cl)  ...}我们现在可以将它传递给设置内容的代码:mh := myHandler{  cl: cl,}http.Handle("/", http.HandlerFunc(mh.handle))更好的方法但是如果我们使用 RTFM(提示!),我们可以做得更好:文档net/http.HandlerFunc说:该HandlerFunc类型是一个适配器,允许将普通函数用作 HTTP 处理程序。因此,如果我们浏览文档以查看“HTTP 处理程序”是什么,我们会得出net/http.Handler哪个是接口类型,并且该接口可以由任何具有方法的数据类型来满足ServeHTTP(http.ResponseWriter, *http.Request)。你看到与 有什么相似之处myHandler.handle吗?正确的。所以我们的类型可以变成type myHander struct {  cl native.Client // I have no idea which type native.Connect returns...}func (*mh myHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {  h, err := createCall(mh.cl)  ...}然后我们可以做mh := myHandler{  cl: cl,}http.Handle("/", &mh)

慕尼黑的夜晚无繁华

您可以将处理程序代码提取到单独的工厂函数中:func MakeHandler(cl *Conn) http.Handler {    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {        // make call        log.Info("Make sample call")        h, err := createCall(cl)        if err != nil {            log.Error("Failed to create call", "error", err)            w.WriteHeader(http.StatusBadGateway)            w.Write([]byte("Failed to create call: " + err.Error()))            return        }        w.WriteHeader(http.StatusOK)        w.Write([]byte(h.ID()))    })  }然后在您的原始范围内使用它。http.Handle("/", otherpkg.MakeHandler(cl))
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go