一、Web应用的工作原理
1.创建第一个简单的Web应用
package main
import (
"fmt"
"log"
"net/http"
)
//创建处理器函数
func handlerTest(w http.ResponseWriter,r *http.Request) {
//两个参数一个从请求中获取东西,一个可以写入回复的报文
fmt.Fprintln(w,"Hello goWeb!!",r.URL.Path)
}
func main() {
http.HandleFunc("/",handlerTest)
//创建路由
err := http.ListenAndServe(":8080",nil)
//Handler参数设为nil时,会使用DefaultServeMux
if err==nil{
log.Fatal("ListenAndServe: ",err)
}//注意错误处理
}
在当前文件夹目录下打开终端,执行
go build main.go
随后在当前目录会生成一个main.exe
的二进制可执行文件,最后再执行
./main.exe
即可启动服务器。
在浏览器地址栏输入
http://localhost:8080
在浏览器中就会显示
二、Web服务器的创建
1.简介
Go 提供了一系列用于创建 Web 服务器的标准库,而且通过 Go 创建一个服务器的 步骤非常简单,只要通过 net/http
包调用 ListenAndServe
函数,传入网络地址以及负责处理请求的处理器( handler )作为参数即可。
如果网络地址参数为空字符串,那 么http服务器默认使用 80 端口进行网络连接;如果处理器参数为 nil,那么服务器将使用默 认的多路复用器 DefaultServeMux,当然,我们也可以通过调用 NewServeMux
函数创 建一个多路复用器。多路复用器接收到用户的请求之后根据请求的 URL 来判断使用哪 个处理器来处理请求,找到后就会重定向到对应的处理器来处理请求。
2.使用DefaultServeMux
(1)使用处理器函数处理请求
package main
import (
"fmt"
"net/http"
)
//创建处理器函数
func handlerTest(w http.ResponseWriter,r *http.Request) {
fmt.Fprintln(w,"正在通过处理器函数处理你的请求")
}
func main() {
http.HandleFunc("/",handlerTest)
http.ListenAndServe(":8080",nil)
}
a)HandleFunc方法
func HandleFunc
func HandleFunc(pattern string, handler func(ResponseWriter, *Request))
HandleFunc
注册一个处理器函数handler
和对应的模式pattern
(注册到DefaultServeMux)。ServeMux的文档解释了模式的匹配机制。
b)处理器函数的实现原理
Go 语言拥有一种 HandlerFunc
函数类型,它可以将一个带有正确签名的函数 f (在这里就是自行创建的处理器函数)转换成一个带有方法 f 的 Handler
。
type HandlerFunc
type HandlerFunc func(ResponseWriter, *Request)
HandlerFunc type
是一个适配器,通过类型转换让我们可以将普通的函数作为HTTP处理器使用。如果f是一个具有适当签名的函数,HandlerFunc(f)
通过调用f实现了Handler接口。
(2)使用处理器处理请求
package main
import (
"fmt"
"net/http"
)
type MyHandler struct{}
func (h *MyHandler) ServeHTTP(w http.ResponseWriter,r * http.Request) {//自行实现方法(即实现接口)
fmt.Fprint(w,"正在通过处理器处理你的请求")
}
func main(){
myHandler :=MyHandler{}
//调用处理器
http.Handle("/",&myHandler)
http.ListenAndServe(":8080",nil)
}
a)Handle方法
func Handle(pattern string, handler Handler)
Handle
注册HTTP处理器handler
和对应的模式pattern
(注册到DefaultServeMux)。如果该模式已经注册有一个处理器,Handle会panic。ServeMux的文档解释了模式的匹配机制。
b)关于处理器Handler的说明
type Handler
type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}
实现了Handler
接口的对象可以注册到HTTP服务端,为特定的路径及其子树提供服务。
ServeHTTP
应该将回复的头域和数据写入ResponseWriter
接口然后返回。返回标志着该请求已经结束,HTTP服务端可以转移向该连接上的下一个请求。
也就是说只要某个结构体实现了Handler接口中的ServeHTTP方法,那就是一个处理器
c)通过Server结构对服务器进行更详细的配置
type Server struct {
Addr string // 监听的TCP地址,如果为空字符串会使用":http"
Handler Handler // 调用的处理器,如为nil会调用http.DefaultServeMux
ReadTimeout time.Duration // 请求的读取操作在超时前的最大持续时间
WriteTimeout time.Duration // 回复的写入操作在超时前的最大持续时间
MaxHeaderBytes int // 请求的头域最大长度,如为0则用DefaultMaxHeaderBytes
TLSConfig *tls.Config // 可选的TLS配置,用于ListenAndServeTLS方法
// TLSNextProto(可选地)指定一个函数来在一个NPN型协议升级出现时接管TLS连接的所有权。
// 映射的键为商谈的协议名;映射的值为函数,该函数的Handler参数应处理HTTP请求,
// 并且初始化Handler.ServeHTTP的*Request参数的TLS和RemoteAddr字段(如果未设置)。
// 连接在函数返回时会自动关闭。
TLSNextProto map[string]func(*Server, *tls.Conn, Handler)
// ConnState字段指定一个可选的回调函数,该函数会在一个与客户端的连接改变状态时被调用。
// 参见ConnState类型和相关常数获取细节。
ConnState func(net.Conn, ConnState)
// ErrorLog指定一个可选的日志记录器,用于记录接收连接时的错误和处理器不正常的行为。
// 如果本字段为nil,日志会通过log包的标准日志记录器写入os.Stderr。
ErrorLog *log.Logger
// 内含隐藏或非导出字段
}
Server
类型定义了运行HTTP服务端的参数。Server
的零值是合法的配置。
package main
import (
"fmt"
"net/http"
"time"
)
type MyHandler struct{}
func (h *MyHandler) ServeHTTP(w http.ResponseWriter,r *http.Request) {
fmt.Fprintln(w,"成功通过Server结构详细配置服务器")
}
func main() {
MyHandler:=MyHandler{}
//通过Server结构对服务器进行更详细的配置
server:=http.Server{
Addr: ":8080",
Handler: &MyHandler,
ReadTimeout: 2*time.Second,
}
server.ListenAndServe()
}
3.使用自己创建的多路复用器
通过NewServeMux方法创建一个多路复用器
func NewServeMux
func NewServeMux() *ServeMux
NewServeMux
创建并返回一个新的*ServeMux
package main
import(
"fmt"
"net/http"
)
func handler(w http.ResponseWriter,r *http.Request){
fmt.Fprintln(w,"NewServeMux")
}
func main() {
mux:=http.NewServeMux()
mux.HandleFunc("/myMux",handler)
http.ListenAndServe(":8080",mux)
}