登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

being23

写给未来的自己

 
 
 
 
 

日志

 
 
关于我

真正的坚定,就是找到力量去做自己喜欢的事情,并为之努力,这样才会觉得生活是幸福的。

go语言闭包  

2014-03-21 20:19:47|  分类: work@oppo |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

闭包的概念、形式与应用一文中,有一总结“对象是附有行为的数据,而闭包是附有数据的行为”。

先看两个例子——

第一个例子来自Go中的闭包

package main 
import "fmt"

func closure01() func(int) int {
    sum := 0
    return func(x int) int {
        sum += x
        return sum
    }
}

func main() {
    myfun := closure01()
    for i := 0; i < 3; i++ {
        fmt.Println(myfun(i))
        //调用 myfun 会执行closure01()内部的匿名函数,i作为参数传递给该函数的变量x,sum就是“附有的数据”
    }
}

输出:

[root@datanode1 demo]# go run closure_demo.go 
0
1
3

上面这个例子是将变量,放到引用环境中。再看一个例子,将函数放到引用环境中(其实在go中,函数也是一种变量,即函数是一阶值)。

package main 
import "fmt"

func closure02(fn func(int, int) int) func(int) int {
    tmp := 1
    return func(x int) int {
        return fn(x, tmp)
    }
}

func add(x int, y int) int {
    return x + y
}

func sub(x int, y int) int {
    return x - y
}

func main() {
    // closure02 稍微复杂一点 —— 它的参数中有一函数类型的变量fn,在内部的匿名函数里调用了fn, 这里嵌套了一层
    myadd := closure02(add)
    fmt.Println(myadd(1))
    // 调用 myadd 会执行 closure02 内部的匿名函数,匿名函数又会执行作为参数传递的函数fn, 函数fn的参数x就是myadd(1)中的1,参数y就是附有数据tmp,所以最终结果就是 x(1) + y(tmp=1) = 2
    mysub := closure02(sub)
    fmt.Println(mysub(1))
    // 同上
}

输出:

[root@datanode1 demo]# go run closure_demo.go 
2
0

为什么要考虑函数放在引用环境中这种场景呢?在应用中,不同的url通常是由不同的handler处理,这一步是通过函数http.HandleFunc定义的

func HandleFunc(pattern string, handler func(ResponseWriter, *Request))

我们所要做的就是针对不同的pattern,定义不同的handler就行了,很简单有木有。问题是如果我们的handler函数不是这种类型func(ResponseWriter, *Request),该怎么办呢?

例如,我们在logic包中有这样一个处理器MyHandler

func MyHandler(req *protocol.ClientRequest, w http.ResponseWriter, r *http.Request, ch chan string) 

解决的方式就是定义一个闭包makeHttpHandler,将我们的处理器MyHandler作为参数fn放到引用环境,在内部匿名函数中调用处理器fn

func makeHttpHandler(
    fn func(*protocol.ClientRequest, http.ResponseWriter, *http.Request, chan string), 
    reqId string, 
    ch chan string
) http.HandlerFunc {
    return func(w http.ResponseWriter, r *http.Request) {
        ...
        fn(someClientRequest, w, r, ch)
        ...
    }
}

这样一来,就可以像通常那样来定义处理器了

http.HandleFunc("/some/pattern", makeHttpHandler(logic.MyHandler, "myString", myChan))

2014-03-21@迈科龙

  评论这张
 
阅读(557)| 评论(0)

历史上的今天

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2018