本文主要讲解go语言web编程中的路由与http服务基本原理。

首先,使用go语言启动一个最简单的http服务:

package main

import (
"log"
"net/http"
) func main() {
http.HandleFunc("/", sayHello)
log.Println("server running...")
log.Fatal(http.ListenAndServe("localhost:4000", nil))
} func sayHello(writer http.ResponseWriter, req *http.Request) {
writer.Write([]byte("hello world!"))
}

编译,运行,浏览器访问 http://localhost:4000/ ,输出 hello world! 。
总的来说,这段代码只是做了两件事情,第一,注册路由,指定客户端请求路径对应的响应函数:
http.HandleFunc("/", sayHello)
第二,启动http服务,监听端口,接受并响应客户端请求:
http.ListenAndServe("localhost:4000", nil)

先看第一件事情——注册路由,指定请求路径对应的响应函数。
首先看 http.HandleFunc() 函数源码:

func HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
DefaultServeMux.HandleFunc(pattern, handler)
}

其中 DefaultServeMux 是go的默认路由器,所以注册路由实际上是由路由器进行的,http.HandleFunc() 函数只是对它进行封装,那么路由器的结构是怎么样的呢?
源码可见:

type ServeMux struct {
mu sync.RWMutex
m map[string]muxEntry
es []muxEntry
hosts bool
}
type muxEntry struct {
h Handler
pattern string
}

其中 ServeMux 结构中的 map[string]muxEntry 就是用来保存请求路径与响应函数之间的映射。从 muxEntry 结构定义可知,响应函数的类型为 Handler,而Handler实际上是一个接口类型,源码如下:

type Handler interface {
ServeHTTP(ResponseWriter, *Request)
}

所以,响应函数需要实现这个接口,才能进行路由注册。
源码中声明了一个 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编程——自定义路由设计

借鉴:
《Go Web编程》

go web编程——路由与http服务的更多相关文章

  1. go web编程——自定义路由设计

    本文主要讲解go语言web编程中自定义路由器的设计.在此之前需要先了解一下go语言web编程中路由与http服务的基本原理,可以参考笔者另一篇博文:go web编程——路由与http服务 . 我们已经 ...

  2. 物联网网络编程、Web编程综述

    本文是基于嵌入式物联网研发工程师的视觉对网络编程和web编程进行阐述.对于专注J2EE后端服务开发的童鞋们来说,这篇文章可能稍显简单.但是网络编程和web编程对于绝大部分嵌入式物联网工程师来说是一块真 ...

  3. ASP.NET MVC编程——路由

    框架自动生成的路由配置 上图中,路由配置文件为App_Start文件夹下的RouteConfig.cs. 代码如下: public class RouteConfig { public static ...

  4. 物联网网络编程和web编程

    本文是基于嵌入式物联网研发project师的视觉对网络编程和web编程进行阐述. 对于专注J2EE后端服务开发的同学来说,这篇文章可能略微简单.可是网络编程和web编程对于绝大部分嵌入式物联网proj ...

  5. Python 四大主流 Web 编程框架

    Python 四大主流 Web 编程框架 目前Python的网络编程框架已经多达几十个,逐个学习它们显然不现实.但这些框架在系统架构和运行环境中有很多共通之处,本文带领读者学习基于Python网络框架 ...

  6. ASP.NET Web API路由系统:路由系统的几个核心类型

    虽然ASP.NET Web API框架采用与ASP.NET MVC框架类似的管道式设计,但是ASP.NET Web API管道的核心部分(定义在程序集System.Web.Http.dll中)已经移除 ...

  7. python web编程-概念预热篇

    互联网正在引发一场革命??不喜欢看概念的跳过,注意这里仅仅是一些从python核心编程一书的摘抄 这正是最激动人心的一部分了,web编程 Web 客户端和服务器端交互使用的“语言”,Web 交互的标准 ...

  8. ASP.NET Web API 路由

    路由系统是请求消息进入ASP.NET Web API消息处理管道的第一道屏障,其根本目的是利用注册的路由表(RouteTable)对请求的URI进行解析以确定目标HttpController和Acti ...

  9. MVC 5 Web编程2 -- URL映射

    ASP.NET MVC 5 Web编程2 -- URL映射(路由原理) 2015-02-12 08:50 by hangwei, 704 阅读, 5 评论, 收藏, 编辑 本章将讲述ASP.NET M ...

随机推荐

  1. leetcode69. x 的平方根 🌟

    题目: 实现 int sqrt(int x) 函数. 计算并返回 x 的平方根,其中 x 是非负整数. 由于返回类型是整数,结果只保留整数的部分,小数部分将被舍去. 示例 1: 输入: 4 输出: 2 ...

  2. POJ 2054 Color a Tree (贪心)

    $ POJ~2054~Color~a~Tree $ $ solution: $ 我们先从题中抽取信息,因为每个点的费用和染色的次数有关,所以我们可以很自然的想到先给权值大的节点染色.但是题目还说每个节 ...

  3. 多边形面积计算公式 GPS经纬度计算面积

    最近在做地图相关面积计算显示工作,百度了很多关于多边形面积计算方面公式和代码,只能说贼费劲,最终完成了把结果展示下     原理:鞋带公式 定义:所述鞋带式或鞋带算法(也称为高斯的面积公式和测量员的式 ...

  4. 17 安全字符串 System.Security.SecureString

  5. nodejs通过async/await来操作MySQL

    在nodejs中从数据库得到数据后是通过回调函数来操作数据的,如果嵌套多层将非常可怕,代码逻辑和可读性将变得非常差.有时用promise也并不能很好得解决问题,因为如果用了promise后,代码将会有 ...

  6. Web上传文件的三种解决方案

    第一点:Java代码实现文件上传 FormFile file = manform.getFile(); String newfileName = null; String newpathname =  ...

  7. 浅析java中的string

    在学习java36讲的时候看到评论区有人提出的一个问题: String s1 = new String("do"); s1.intern(); String s2 = " ...

  8. 升级至webpack4.x踩坑记(热更新局部更新失败的问题修复)

    零.前言 webpack升级的时候,会碰到各种个样的问题,大多数网上都能查到解决方案最简单的方案. 思路如下: 1.把css-loader,xxxloader等依赖都升级到最新 2.根据webpack ...

  9. tr:hover变色的问题

    做表格隔行变色(高亮显示),可以通过设置css中的 tr:hover伪类属性达到效果, 但是,会出一点小问题.td的背景色会覆盖tr的背景色, 在tr:hover下边加上一句:tr:hover td{ ...

  10. Js定义一个表单并提交

    Js定义一个表单 var form = $("<form>"); //定义一个form表单 form.attr('style', 'display:none'); // ...