京东建站模板,wordpress案例插件,芜湖十大企业排名,本地的唐山网站建设文章目录 http.Handle和http.HandleFunc的区别http.Handle分析type func巧妙运用 http.HandleFunc分析总结参考资料 http.Handle和http.HandleFunc的区别
http.Handle和http.HandleFunc的区别体现了Go语言接口的巧妙运用
下面代码启动了一个 http 服务器#xff0c;监听 808… 文章目录 http.Handle和http.HandleFunc的区别http.Handle分析type func巧妙运用 http.HandleFunc分析总结参考资料 http.Handle和http.HandleFunc的区别
http.Handle和http.HandleFunc的区别体现了Go语言接口的巧妙运用
下面代码启动了一个 http 服务器监听 8080 端口并注册路由。实现这两个路由注册的方法有点不同一个使用 http.Handle另一个使用 http.HandleFunc 下面来看看这两个之间的区别
http.Handle分析
我们简单看一下http.Handle函数 这个 Handler 类型是什么呢其实它就是一个接口包含一个 ServeHttp() 的方法
type Handler interface {ServeHTTP(ResponseWriter, *Request)
}在Go语言常规代码中接口一般是这样用的
// Sayer 接口
type Sayer interface {say()
} type dog struct {}type cat struct {} // dog实现了Sayer接口
func (d dog) say() {fmt.Println(汪汪汪)
}// cat实现了Sayer接口
func (c cat) say() {fmt.Println(喵喵喵)
} 先写一个接口再写一个结构体最后将结构体与方法相关联也就是这个结构体类型dog实现了接口。 其实type关键字作用是声明类型这里应该写为dog类型实现Sayer接口cat类型实现Sayer接口比较合适。一个对象只要全部实现了接口中的方法那么就实现了这个接口。 我们再看一个例子
package mainimport fmttype Sayer interface {say()
} type dog int// dog实现了Sayer接口
func (d dog) say() {fmt.Println(汪汪汪)
}func main() {var d dogd.say()
}没错我们把int类型重新定义为一个新的类型这个类型叫dogdog这个类型也实现了Sayer接口。所以玩转一个接口一般分为三步
第一步定义一个接口类型第二步定义一个非接口类型第三步在非接口类型上实现接口。
所以第二步的代码只要定义一个非接口类型即可。
type func巧妙运用
我们知道func也是一种类型那可以试着用func类型实现接口。
type Sayer interface {say(str string)
} type Dog func(string)func (f Dog) say(str string) {f(str)
}代码写到IDE上也没有报错说明这段代码是可行的。代码中的f(str)又是什么意思。f(str)看起来有点像一个名叫f的函数传入了一个str的参数当方法被调用时(注意Go语言中方法与函数的区别)这个函数就行执行只不过这个函数的类型是Dog类型。等等有点不对。这个函数就行执行执行了什么所以执行之前一定要有一个Dog类型的实例。可以是一个有名称的函数也可以是一个匿名函数
package mainimport fmttype Sayer interface {say(str string)
} type Dog func(string)func (f Dog) say(str string) {f(str)
}func main() {d : Dog(func(str string){fmt.Println(转换类型)})d(开始执行)
}特别要注意的是这段代码中的Dog(func(str string)表示是一个强制转换把匿名函数转为Dog类型。理解了type func再看方法二也就不难了。
http.HandleFunc分析
从代码上看函数二比函数一少定义了一个结构体简洁一些写起来也方便一些。那为什么函数二比函数一少写了一个结构体? 下面看代码
func HandleFunc(pattern string,handler func(ResponseWriter, *Request)) {DefaultServeMux.HandleFunc(pattern, handler)
}通过源码得知HandleFunc是http包下的一个大写字母开头的公开函数该函数接收两个参数一个是路由匹配的字符串另外一个是 func(ResponseWriter, *Request) 类型的函数。
然后继续调用 DefaultServeMux.HandleFunc(pattern, handler)
func (mux *ServeMux) HandleFunc(pattern string,handler func(ResponseWriter, *Request)) {if handler nil {panic(http: nil handler)}mux.Handle(pattern, HandlerFunc(handler))
}可以看到这里把 handler 转换成了 HandlerFunc 类型而 HandlerFunc 类型则如下所示
// The HandlerFunc type is an adapter to allow the use of
// ordinary functions as HTTP handlers. If f is a function
// with the appropriate signature, HandlerFunc(f) is a
// Handler that calls f.
type HandlerFunc func(ResponseWriter, *Request)// ServeHTTP calls f(w, r).
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {f(w, r)
}该类型实现了 ServeHTTP 接口所以其也可以转换成 Handler 类型接下来调用 mux.Handle(pattern string, handler Handler) 就跟 http.Handle 的流程是一样的了。
总结
http.Handle的使用方法和面向对象编程差不多第一步定义一个接口类型第二步定义一个非接口类型第三步在非接口类型上实现接口。
http.HandleFunc使用上简洁一些但原理比较复杂。先定义一个函数参数类型返回值都要和ServeHTTP一样再将它强转为HandlerFunc类型HandlerFunc类型有一个方法叫ServeHTTP这方法会执行一个名叫f的函数这个函数的类型就是HandlerFunc。因为一个对象只要全部实现了接口中的方法那么就实现了这个接口。所以HandlerFunc类型实现了type Handler interface这个接口。所以我们只要写一个匿名函数内部就会为我们转为HandlerFunc类型。
参考资料
理解go的function types golang中 type func() 用法分析