前言:
今天是2019-11-25阴天,开始学习goweb,前天刚做完一个gotcp项目,goweb是基于http协议的,http协议又是基于tcp协议封装的,应该问题不大
package http
import “net/http”
http包提供了HTTP客户端和服务端的实现。
案例一:
- 创建一个处理器函数,使用适配器调用该函数,再创建一个server服务,默认监听8080
package main
import (
"fmt"
"net/http"
)
// 创建一个处理器函数,从参数名猜,一个响应写入,一个请求
func ServeHTTP(responseWrite http.ResponseWriter,request *http.Request){
fmt.Fprintln(responseWrite,"hello world",nil)
}
func main(){
// HandlerFunc type是一个适配器,通过类型转换让我们可以将普通的函数作为HTTP处理器使用。
// 如果f是一个具有适当签名的函数,HandlerFunc(f)通过调用f实现了Handler接口。
// type HandlerFunc func(ResponseWriter, *Request)
http.HandleFunc("/",ServeHTTP)
// ListenAndServe使用指定的监听地址和处理器启动一个HTTP服务端。处理器参数通常是nil
http.ListenAndServe("0.0.0.0:8080",nil)
}
案例解析:
- HandleFunc是一个适配器可以通过类型转换将普通函数作为HTTP处理器使用,client访问server路径匹配到 / 则调用该处理器
- ServeHTTP处理器函数,参数是既定的,适配器可以调用该函数完成对用户请求响应
- ListenAndServe启动一个HTTP.server这个和tcp创建服务实例类似
案例二:
- 创建一个空结构体,实现一个ServeHTTP方法,也就实现了Handler接口,实例化一个空结构体对象,进而调用ServerHTTP方法
- Handler也是一个适配器,此时就可以使用
http.Handle("/",&ishandler)
进行处理器调用
package main
import (
"fmt"
"net/http"
"time"
)
type myHandler struct{
}
func (ihandler *myHandler)ServeHTTP(response http.ResponseWriter,request *http.Request){
fmt.Fprintln(response,"myHnadler 服务器配置处理请求",nil)
}
func main(){
ishandler := myHandler{
}
// 处理器一定要写到服务端前要不然调用不到
http.Handle("/",&ishandler)
http.ListenAndServe("0.0.0.0:8080",nil)
}
案例解析:
- 自己写一个ServerHTTP方法则实现了Handle接口,Handle接口也是一个适配器,则进行处理器调用就变成了
http.Handle("/",&ishandler)
,其他和第一种方式相同
注意:
- 自己实现Handle接口在调用处理器就要用Handle接口(适配器)
案例三:
- 自定义初始化server配置
package main
import (
"fmt"
"net/http"
"time"
)
type myHandler struct{
}
func (ihandler *myHandler)ServeHTTP(response http.ResponseWriter,request *http.Request){
fmt.Fprintln(response,"myHnadler 服务器配置处理请求",nil)
}
func main(){
ishandler := myHandler{
}
server := &http.Server{
Addr: ":8080",
Handler: &ishandler,
ReadTimeout: 10 * time.Second,
WriteTimeout: 10 * time.Second,
MaxHeaderBytes: 1 << 20,
}
server.ListenAndServe()
}
案例解析:
- 自定义server配置后启动server服务,调用处理器就都在server中封装了,则直接使用server去调用ListenAndServer起一个服务就ok了
案例四:
- 自己创建多路复用器匹配调用和url匹配的处理器
- 多路复用器创建函数NewServeMux
package main
import (
"fmt"
"net/http"
_"time"
)
type myHandler struct{
}
func (ihandler *myHandler)ServeHTTP(response http.ResponseWriter,request *http.Request){
fmt.Fprintln(response,"通过自己创建的多路复用器配置处理请求",nil)
}
func main(){
// 自定义一个serveMux(多路复用器)
serveMux := http.NewServeMux()
ishandler := myHandler{
}
// 处理器一定要写到服务端前要不然调用不到
serveMux.Handle("/serverMux",&ishandler)
http.ListenAndServe("0.0.0.0:8080",serveMux)
}
注意:
- 如果自己创建多路复用器则ListenAndServe一定要加serveMux参数,因为尾部参数为空会吊用默认多路复用器调用,自定义后还为空则调用不到匹配不到对应资源
http协议简单理解
-
有状态:在server眼里client可能是不同的,不同的请求会有不同的处理方式,例如redis
-
有状态就是有数据存储功能。有状态对象(Stateful Bean),就是有实例变量的对象,可以保存数据,是非线程安全的。在不同方法调用间不保留任何状态。
-
无状态:在server眼里所有的client都是一样的没什么区别,处理方式都是统一的,例如nginx
-
无状态就是一次操作,不能保存数据。无状态对象(Stateless Bean),就是没有实例变量的对象.不能保存数据,是不变类,是线程安全的。
请求报文案例演示:
server.go
package main
import (
"fmt"
"net/http"
)
func ServeHTTP(responseWrite http.ResponseWriter,request *http.Request){
fmt.Fprintln(responseWrite