Go原理go语言两行代码创建http服务

Posted C+++++++++++++++++++

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Go原理go语言两行代码创建http服务相关的知识,希望对你有一定的参考价值。


由简单http服务引出问题

源码如下:创建一个在8080端口服务的程序

package main

import "net/http"

func main() 
	//TODO 添加路由过程处理
	http.HandleFunc("/",func(w http.ResponseWriter, r *http.Request) w.Write([]byte("Hello World!")))
	//TODO 启动服务
	http.ListenAndServe(":8080", nil)

我们虽然看似非常简单的就添加了路由处理回调以及启动服务,但是我们感觉啥也没懂啊,就是很空洞,不清楚这个具体过程的那种空洞感,导致我初学时虽然用起来简单,但我属于那种不弄清楚原理就记不住的那一类人,故写了一个总结

浅析原理

Handler接口

作用

这个接口存在的目的主要是为了让所有的回调函数处理动作统一,也就是只要实现了这个接口,就可以作为回调函数传入到一些地方使用。

接口的源码:接口内定义了ServeHTTP方法

ServeMux类

作用

go语言内置实现的Handler用于主路由,将服务转法给他内部注册的其他Handler。具体到使用过程中就是,我可以设置 '/hello' 这个前缀名的处理逻辑函数为一个自定义的Handler,也可添加处理其他前缀的Handler。

具体可看下面图片:

初始化

初始化只需要调用http包的NewServeMux即可

具体的ServeMux类的成员对现在的我来说还难以理解,所以这里只需要调用它提供的方法得到具体的类的实例即可。

根据以上源码来看,我们也可以自己直接new 一个ServeMux

基本方法

  1. Handle方法

    需要传入字符串和一个实现Handler接口的类来进行注册。

  2. HandleFunc方法


    只需要传入字符串和一个特定类型的函数即可。

需要注意:HandleFunc方法实际还是调用的Handle方法,只不过在内部多了一步把函数转成Handler的过程。

对应以下源码:

创建了一个类型,并实现了Hanlder接口

Serve类

作用

用于给Handler启动对应端口的服务。

初始化

Serve是一个结构体,里面有很多成员,但我们需要初始化的成员一般只有这两个:Addr和Handler。

Addr用于指定服务的端口号,Handler用于指定处理该端口号请求的对象。

基本方法

基本方法:ListenAndServe()调用该方法后可以对Addr所表示的端口进行服务,然后是调用Handler进行服务。

简单使用过程:

package main

import "net/http"

func main() 
	s := &http.ServerAddr: ":8080", Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) 
		w.Write([]byte("Hello world!"))
	)
	//TODO 启动服务
	s.ListenAndServe()

现在你只要输入8080端口,所有的服务都是返回Hello world了,原因是你把主路由逻辑用了自己写的Handler,而内部的ServeMux能够提供将请求处理转发,而你自己写的Handler则未有这个逻辑

回到最开始的源代码

有了前面对三个基本结构的剖析,那么现在最开始那两行代码再跳转到内部源码就能够很清晰的知道是什么个情况了!

	//TODO 添加路由过程处理
	http.HandleFunc("/",func(w http.ResponseWriter, r *http.Request) w.Write([]byte("Hello World!")))
	//TODO 启动服务
	http.ListenAndServe(":8080", nil)

都是基于DefaultServeMux

DefaultServeMux 就是http这个文件中定义的对外导出的变量,而这个变量套了一层,实际上还是ServeMux类型。所以DefaultServeMux 就是http包事先给你默认创建好的ServeMux变量。

知道这个有什么用呢?

我们之前讨论的所有服务建立过程和响应请求过程,都是通过类的方法来进行,而我们最开始的两行代码却只需要调用两个函数,你难道不感到奇怪吗?

知道了http包里面有个默认的变量,那这个疑问就迎刃而解了,当我们调用这两个函数的时候,实际上就是在http包里面调用DefaultServeMux或者Serve类的方法而已

http.HandleFunc()

源码:

http.ListenAndServe()

源码:

当handler传值为nil时,初始化Server的Handler为DefaultServeMux

以上是关于Go原理go语言两行代码创建http服务的主要内容,如果未能解决你的问题,请参考以下文章

Go语言异步服务器框架原理和实现

使用 Go 语言创建 WebSocket 服务

go语言聊天室实现(六)创建HTTP连接,并升级为长连接

Go语言10-http和mysql

Go 语言 Web 编程系列— HTTP 请求处理的底层运行机制

5.Go语言高并发与微服务实战 --- 构建 Go Web 服务器