この記事では、ルーティングおよびサービス行くのhttpウェブプログラミング言語の基本的な原則を説明しています。
まず、サービスを開始する最も簡単な言語を行くのhttp:
メインパッケージ
のインポート(
"ログ"
""ネット/ HTTPを
)
メインfuncを(){
http.HandleFunc( "/"、のsayHello)
log.Println( "サーバーで実行...")
log.Fatal(http.ListenAndServe( "localhostの:4000" 、nilの))
}
のsayHello(作家http.ResponseWriter FUNC、REQ * http.Request){
!writer.Write([]バイト( "ハローワールド"))
}
コンパイルおよびアクセスブラウザでhttpを実行します:// localhostを:4000 /、出力ハローワールド!
全体的に、ちょうど最初、登録、ルーティング、クライアントの要求応答機能へのパスを指定し、2つのことを実行するには、このコード:
(、「/」のsayHello)http.HandleFunc
第二には、リスニングポート、HTTPサービスを開始します受信し、クライアントの要求に応答:
http.ListenAndServe( "localhostを:4000"、nilに)
最初のものを見て-要求応答機能に対応する登録ルート指定されたパスを。
まず見た目http.HandleFunc()関数出典:
FUNC HandleFunc(パターン文字列、ハンドラFUNC(ResponseWriter、*リクエスト)){
DefaultServeMux.HandleFunc(パターン、ハンドラ)
}
そう、実際にルータによって登録されているデフォルトのルーティングルータ、外出先でDefaultServeMux、http.HandleFunc()関数は、単純に、ルータの構造がどのようにそれの一種である、それをカプセル化しますか?
可視出典:
{ServeMux構造体入力
ミューsync.RWMutex型
muxEntry Mマップ[文字列]
ES [] muxEntryの
ホストはBOOL
}
muxEntry構造体{型
Hハンドラ
パターン文字列を
}
前記ServeMux構造マップ[ストリング] muxEntry要求は、パスと応答関数との間のマッピングを保存するために使用されます。構造から理解MuxEntryは、ハンドラの応答関数のタイプを定義して、ハンドラが実際にインタフェースタイプ、ソースコードは以下の通りです。
入力ハンドラ・インタフェース{
ServeHTTP(ResponseWriter、*リクエスト)
}
所以,响应函数需要实现这个接口,才能进行路由注册。
源码中声明了一个 HandlerFunc 类型,就实现了 Handler 接口:
type HandlerFunc func(ResponseWriter, *Request)
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
f(w, r)
}
所以,只要我们的响应函数满足结构 func (http.ResponseWriter, *http.Request) ,即可进行路由注册,注册路由时,路由器会将其类型强制转换为 HandlerFunc 。其中,http.ResponseWriter参数包含了响应头、响应数据等响应相关信息,而http.Request参数则包含了请求头、请求参数等请求相关信息。
再看第二件事情,启动http服务,监听端口,接受并响应客户端请求。
首先看 http.ListenAndServe() 函数源码:
func ListenAndServe(addr string, handler Handler) error {
server := &Server{Addr: addr, Handler: handler}
return server.ListenAndServe()
}
其中 Server 即为http服务器类型,其结构如下(省略了部分字段):
type Server struct {
Addr string
Handler Handler
......
}
其中 Addr 为服务器监听的ip与端口字符串,Handler 为路由器,指定其为 nil 时,go会使用它的默认路由器 DefaultServeMux (调用 http.HandleFunc() 方法注册路由时就是注册到这个默认的路由器)。
服务器监听端口,接受客户端请求,并做出响应,这个过程可借助《go web编程》中的一张图示来帮助理解:
图中有两个红色矩形标记,第一个,说明针对客户端的每一个请求,go都会使用一个Goroutine进行响应,保证每个请求都能独立,相互不会阻塞,可以高效响应网络事件;第二,最终调用默认路由器的 ServeHTTP(w ResponseWriter, r *Request) 方法进行路由,从请求路径与响应函数的映射中找到对应的handler,最后调用handler的 ServeHTTP(w ResponseWriter, r *Request) 方法,从上面 HandlerFunc 类型的 ServeHTTP(w ResponseWriter, r *Request) 方法可知,其实最后调用的就是我们注册路由时定义的响应函数本身。
使用go默认路由器的不足之处是,不满足RESTful规则,而且对请求路径的路由只支持绝对匹配,不支持正则匹配。如果想设计一些特殊、简便的路由,需要设计一个自定义路由器,并让go的http服务器使用这个自定义路由器。关于自定义路由器的设计,可以参考笔者另一篇博文:
借鉴:
《Go Web编程》