请从github下载配套代码: https://github.com/shuningzhang/learn_golang 电子书下载地址: https://u19702000.ctfile.com/dir/19702000-33357795-bb2f31/
到目前为止,我们其实已经实现了一个类似Nginx的Web服务器软件模型。虽然整个软件还比较脆弱,但基本的功能已经有了,可以浏览基本的静态页面,并且可以包含图片等内容。
今天我们继续完善这个程序,在完善的过程中我们不断的引入新的Go语言的内容。今天主要学习如下几方面的内容:
- 学习Go语言中的map数据类型
- HTTP协议中关于内容类型的规定
- 修改服务端程序代码,可以根据请求扩展名生成内容类型
Go语言中的map
map是一种Key-Value映射,可以理解为哈希表,它通过一个Key快速的找到Value。map中的Key是无序的集合。
map的定义
在定义map类型变量的时候需要分别指定Key和Value的类型,同时也就是说map中Key和Value是可以多种类型的。如下代码是使用map的基本步骤,先是定义变量,然后是为变量分配空间。
var variable_name map[key_type]value_type /*定义变量*/
variable_name = make(map[key_type]value_type) /*分配空间*/
当然,也可以一次性的进行变量的定义:
variable_name := make(map[key_type]value_type)
使用起来也是非常简单,下面是一个简单的例子:
HTTP的内容类型
前文我们介绍过,Web服务应答数据的时候,都要指定内容的类型。这样浏览器根据内容的类型进行渲染。比如如果是html,则进行解释渲染,形成文档内容;如果是图片则需要渲染成图像效果。如图是Web应答的消息头,其中红色方框中的Content-Type是内容的类型。
内容类型很多,这里不一一介绍,下面表中是比较常见的类型。
文本类型
图片类型
类型非常多,具体可以参考RFC,这里就不详细介绍了,大家有个感官的认识就行。
服务端代码完善
有了上面map的基本使用方法的知识及HTTP内容后,我们就可以继续完善Web服务对应答类型的处理。通过上一节的表格,我们可以确定基本思路就是根据请求路径中文件名的扩展名称进行处理。但有2种特殊情况需要考虑:
- 请求根路径的情况,也就是路径为/的时候,此时我们默认为index.html进行处理
- URL路径中有参数的情况,此时需要考虑如何获取扩展名
首先定义一个全局变量,用来存储扩展名与内容类型的对应关系,这里变量类型就是我们前面学的map类型。
var content_type map[string]string
然后我们实现了一个函数对这个全局变量进行初始化,这里初始化了部分关键类型,并不是全部类型。
然后需要对主函数进行修改,在进入主函数的地方调用该初始化函数:
另外, 还需要修改原来请求消息头解析部分的代码,能够根据扩展名选取类型:
至此,修改完成,可以按照之前的方法自行进行测试验证。
后回顾一下,这次我们主要做了2件事情,一个是学习了如何使用Go语言中的map类型,而是对现有应答类型进行了完善,与协议要求保持一致。