本文视频地址
一 函数可以怎么用
1 在函数内创建
// $GOROOT/src/runtime/print.go
func hexdumpWords(p, end uintptr, mark func(uintptr) byte) {
p1 := func(x uintptr) {
var buf [2 * sys.PtrSize]byte
for i := len(buf) - 1; i >= 0; i-- {
if x&0xF < 10 {
buf[i] = byte(x&0xF) + '0'
} else {
buf[i] = byte(x&0xF) - 10 + 'a'
}
x >>= 4
}
gwrite(buf[:])
}
...
}
在 hexdumpWords 函数内部,变量 p1被匿名函数赋值。
2 作为类型
使用函数来自定义类型
// $GOROOT/src/net/http/server.go
type HandlerFunc func(ResponseWriter, *Request)
3 存储到变量中
// $GOROOT/src/runtime/vdso_linux.go
func vdsoParseSymbols(info *vdsoInfo, version int32) {
if !info.valid {
return
}
apply := func(symIndex uint32, k vdsoSymbolKey) bool {
sym := &info.symtab[symIndex]
typ := _ELF_ST_TYPE(sym.st_info)
bind := _ELF_ST_BIND(sym.st_info)
...
*k.ptr = info.loadOffset + uintptr(sym.st_value)
return true
}
...
}
4 作为参数传入函数
$GOROOT/src/time/sleep.go
func AfterFunc(d Duration, f func()) *Timer {
t := &Timer{
r: runtimeTimer{
when: when(d),
f: goFunc,
arg: f,
},
}
startTimer(&t.r)
return t
}
5.作为返回值从函数返回
// $GOROOT/src/strings/strings.go
func makeCutsetFunc(cutset string) func(rune) bool {
if len(cutset) == 1 && cutset[0] < utf8.RuneSelf {
return func(r rune) bool {
return r == rune(cutset[0])
}
}
if as, isASCII := makeASCIISet(cutset); isASCII {
return func(r rune) bool {
return r < utf8.RuneSelf && as.contains(byte(r))
}
}
return func(r rune) bool { return IndexRune(cutset, r) >= 0 }
}
二 函数作为“一等公民”的特殊运用
1. 像整型变量那样对函数进行显式转型
func Welcome(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, “欢迎来到Go语言的世界!\n")
}
func main() {
http.ListenAndServe(":8080", http.HandlerFunc(Welcome))
}
// $GOROOT/src/net/http/server.go
func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}
可以看到ListenAndServe方法的第二个参数 handler ,而这里 handler 参数的类型 http.Handler 接口。
// $GOROOT/src/net/http/server.go
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
http.Handler 接口只有一个ServeHTTP方法,我们可以看到它的原型是func(http.ResponseWriter, *http.Request),与Welcome原型一模一样。
// $GOROOT/src/net/http/server.go
type HandlerFunc func(ResponseWriter, *Request)
// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
HandlerFunc实现了ServeHTTP方法,也就实现了Handler接口,函数 Welcome 显式转换为 HandlerFunc 类型。