Golang个人总结(Web部分)
本文最后更新于 226 天前,其中的信息可能已经有所发展或是发生改变。如有疑问或错误请反馈至邮箱super.lucky.qu@gmail.com

前言

Golang个人总结的Web部分由本人跟学教材时的个人理解与做题总结而来,难免具有很多错误,如发现请指正,谢谢!

本文题为个人总结,实则叫每日总结比较合适,目前记录为按每天来记录总结,待学习完后可能会重构为结构性更强的个人总结

电脑端可以于左栏“文章目录”来索引到指定小节,手机端可以通过左上角按钮唤出菜单索引到指定小节

正文

Day01-HelloWorld和处理Handle

HelloWorld

声明一个http.Server结构体类型的变量,其中结构体中Addr字段代表地址,:8080则会默认监听localhost:8080端口,第二个是参数是一个Handle类型,填写nil可以调用DefaultServeMux,是一个默认的多路复用器,然后编写函数体内的内容,最后调用监听并服务方法,自定义一个Handle的方法是通过声明一个结构体,然后实现Handler接口的方法,是一个名为ServeHTTP的方法,接受两个参数,第一个参数是类型为http.ResponseWrite的参数,第二个参数是一个类型为http.Request的指针,例:

package main

import(
    net/http
)
//自定义Handler
type HelloHandle{}

//实现Handler接口中的ServeHTTP方法
func (HelloHandle)ServeHTTP(w http.ResponsWriter, r *http.Request){
    //函数体内为处理请求的方法
    w.Write([]byte("Hello World"))
}

func main (){
    s := http.Server("localhost:8080",nil)//调用DefaultServeMux
    http.Handle("/Hello",HelloHandle{})
    s.ListenAndServe()//开始服务
}

依次,就实现了将自定义Handler注册到DefaultServeMux并且访问localhost:8080/hello就会得到Hello World

Day02

概括

内容有内置的五个Handler,请求(Request),Form以及其方法,ResponseWriter

内置的Handler

  • http.NotFoundHandler
  • 函数签名: func NotFoundHandler() Handler
  • 功能: 对于任何请求,都返回404 page not found。
  • http.RedirectHandler
  • 函数签名: func RedirectHandler(url string, code int) Handler
  • 功能: 重定向Handler,url指要跳转的链接,code表示跳转的状态码(3xx)。
  • http.StripPrefix
  • 函数签名: func StripPrefix(prefix string, h Handler) Handler
  • 功能: 修饰Handler,意为“剥除前缀”,去除掉第一个参数内的前缀后调用第二个参数中的handler。如果提供的URL与前缀不符,则会返回404。prefix即为前缀,剥除前缀之后将剥除后的URL调用第二个参数的handler。
  • http.TimeoutHandler
  • 函数签名: func TimeoutHandler(h Handler, dt time.Duration, msg string) Handler
  • 功能: 修饰Handler,第一个传入的参数是调用(修饰)的Handler,第二个参数是指定的运行时间(单位是时间),第三个是在指定的运行时间内没有处理完返回的超时消息。
  • http.FileServer
  • 函数签名: func FileServer(root FileSystem) Handler
  • 功能: 返回一个Handler,使用基于root的文件系统来处理请求,其中,FileSystem是一个接口。
  • 接口定义:
    type FileSystem interface { Open(name string) (File, error) }
  • 常用实现: http.Dir("文件路径")
    func (d Dir)Open(name string)(File, error)

请求(Request)

HTTP消息分为两种,HTTP Request和HTTP Response(请求和响应)
他们具有相同的结构:

  • 请求行
  • 0个或多个Header
  • 空行
  • 可选的消息体(Body)

在net/http包中提供了用于表示http消息结构的东西,其中用来表示请求的就叫做Request,Request是一个结构体,代表了客户端发送的HTTP消息信息,在Request的字段中,有几个重要的字段:

  • URL
  • Header
  • Body
  • Form、PostForm、MultipartForm

通过Request内方法还可以访问其中的Cookie、URL、User Agent等信息,Request可以代表发送到服务器等请求,也可以代表客户端发送的请求

URL

URL字段代表了请求中的请求行的部分内容(不包含最前面的http方法和后面的http版本),其字段是指向url.URL的一个指针,url.URL是一个struct

URL的通用格式为:

//方括号内为可选项
scheme://[userinfo@]host/path[?query][#fragment]

URL的查询字符串

URL的查询字符串 (URL Query)

  • RawQuery
  • 功能: 提供实际查询的字符串。
  • 示例:
    • URL: http://www.luckyqu.cn/post?id=123&thread_id=456
    • RawQuery的值: id=123&thread_id=456
  • URL Fragment
  • 功能: 如果是从浏览器发出的请求,那么Fragment无法被提取,因为浏览器在发送请求的时候会去掉fragment部分。

Header

  • 概述
  • 功能: HTTP消息的header是通过Header类型来描述的,它是一个map,用来表示HTTP Header中的Key-Value对。
  • 类型: map[string][]string
    • key的值为stringvalue[]string类型。
  • 设置Header
  • 创建新的key:
    • 在设置key的时候会创建一个空的[]string作为value,value里面的第一个元素就是header的值。
  • 添加新的value:
    • 为指定的key添加一个新的value执行append操作即可。
  • 获取Header
  • 获取全部:
    • 使用r.Header字段获取全部,返回一个map。
  • 获取特定key的value:
    • 使用r.Header["Accept-Encoding"]获取给定key的一个value,返回值是[gzip, deflate][]string类型)。
  • 获取特定key的第一个value:
    • 使用r.Header.Get("Accept-Encoding")返回gzip, deflate(字符串类型,多个值用逗号隔开)。

请求的Body

  • 概述
  • 功能: 请求和响应都是使用Body字段来表示Body的。
  • 类型: io.ReadCloser接口
    • 实现了io.Readerio.Closer接口。
  • 接口方法
  • Reader接口:
    • Read(p []byte) (n int, err error): 读取数据到p中,返回读取的字节数和可选的错误。
  • Closer接口:
    • Close() error: 关闭资源,返回可选的错误。
  • 读取Body内容
  • 方法: 使用BodyRead方法读取内容。
  • 获取长度: 使用r.ContentLength获取Body的长度。

URL.Query

  • 概述
  • 功能: 查询参数(Query)。
  • 方法: r.URL.Query()会返回查询字符串对应的map[string][]string
  • 获取特定key的value
  • 方法: r.URL.Query().Get(key)会返回传入key对应的第一个value。

Form

前置知识

  • 通过表单发送请求
  • 示例:
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Form Test</title>
</head>
<body>
<form action="/File" method="post" enctype="application/x-www-form-urlencoded">
  <label>
    <input type="text" name="first_name"/>
  </label>
  <label>
    <input type="text" name="last_name"/>
  </label>
  <input type="submit"/>
</form>
</body>
</html>
  • 解释:
    • action属性对应处理的路径。
    • method属性后跟post表示这是一个POST请求。
    • input表示输入块,type="text"表示文本输入,type="submit"表示提交按钮。
  • 表单数据的发送
  • 数据格式:
    • 表单内的数据会以name-value对的形式,通过POST请求发送出去,数据内容在POST请求的Body里面。
  • Content-Type:
    • 通过表单的enctype属性来指定,enctype的默认值为application/x-www-form-urlencoded
    • 浏览器至少要求支持application/x-www-form-urlencodedmultipart/form-data(HTML5需额外支持text/plain)。
  • 不同的Content-Type
  • application/x-www-form-urlencoded:
    • 浏览器会将表单数据编码到查询字符串内,与URL一同发送给服务器。
    • 例如,点击提交后发送的就是:
      first_name=sau%20sheong&last_name=chang
  • multipart/form-data:
    • 每一个name-value会被转换为一个MIME消息部分,每一个部分都有自己的Content-TypeContent-Disposition
    • 例如:
      Content-Disposition: form-data; name="first_name" sau sheong Content-Disposition: form-data; name="last_name" chang
  • 选择合适的Content-Type:
  • 当数据为简单文本时,使用表单URL编码(application/x-www-form-urlencoded)。
  • 当有大量数据时,例如上传文件,使用多部分MIME形式(multipart/form-data)。
  • 表单的method属性:
  • 通过表单的method属性可以设置POST还是GET。
  • GET请求没有Body,所有的数据都通过URL的name-value对来发送。

正文

  • Request上的函数
  • Form:
    • Form字段包含所有表单和URL参数。
  • PostForm:
    • PostForm字段仅包含POST表单数据。
  • MultipartForm:
    • MultipartForm字段用于处理multipart/form-data
  • 解析表单数据
  • 通常做法:
    • 先调用ParseFormParseMultipartForm来解析请求。
    • 然后再相应地访问FormPostFormMultipartForm字段。
  • PostForm字段
  • 获取特定值:
    • 例如,如果只想得到first_name这个key对应的value,可以使用r.Form["first_name"],它返回一个包含一个元素的slice:["Dave"]
  • 处理重复键:
    • 如果表单和URL里有同样的key,那么它们都会放在一个slice里,表单里的值靠前,URL里的值靠后。
  • 仅获取表单数据:
    • 如果只想要表单的key-value对,不要URL的,可以使用PostForm字段。
  • 限制:
    • PostForm只支持application/x-www-form-urlencoded
  • MultipartForm字段
  • 使用方法:
    • 想要使用MultipartForm字段,首先必须调用ParseMultipartForm方法。
    • 这个方法会在必要的时候自动调用ParseForm方法。
    • 参数是需要读取数据的最大长度(字节数)。
  • 返回类型:
    • MultipartForm只包含表单的key-value对。
    • 返回类型是一个struct,而不是map,这个struct中有两个map:
    • 第一个map的key是string,value是[]string
    • 第二个map的key是string,value是文件。
  • FormValue和PostFormValue
  • FormValue:
    • 返回Form字段中指定Key对应的第一个value,无需调用ParseFormParseMultipartForm
  • PostFormValue:
    • 返回PostForm字段中指定Key对应的第一个value,仅限于POST表单数据。
  • 注意事项:
    • 以上两个方法都会调用ParseMultipartForm方法,但如果表单的enctype设置为multipart/form-data,调用ParseMultipartForm方法后无法通过FormValue获得想要的值。
  • 上传文件
  • 常规方法:
    • 首先调用ParseMultipartForm方法,从File字段中获得FileHeader,调用其Open方法来获得文件,可以使用ioutil.ReadAll函数把文件内容读取到byte切片中。
  • 简便方法:
    • 使用FormFile方法,无需调用ParseMultipartForm方法。
    • 返回指定key对应的第一个value,同时返回FileFileHeader,以及错误信息。
    • 面对只上传一个文件的形式,这种方式会更快。
  • 处理非表单的POST请求
  • 限制:
    • 不是所有的POST请求都来自于表单,ParseForm无法处理application/json
  • MultipartReader
  • 函数签名:
    • func (r *Request) MultipartReader() (*multipart.Reader, error)
  • 功能:
    • 如果是multipart/form-datamultipart混合的POST请求,返回一个MIME multipart reader。
    • 否则返回nil和一个错误。
  • 用途:
    • 可以使用该函数代替ParseMultipartForm来把请求的body作为stream进行处理。
    • 不是把表单作为一个对象处理,也不是一次性获得整个map,而是逐个检查来自表单的值,然后每次处理一个。

ResponseWriter&内置的Response

ResponseWriter

  • 概述
  • 用途: 从服务器向客户端返回响应需要使用ResponseWriter
  • 类型: ResponseWriter是一个接口,handler用它来返回响应。
  • 底层结构: 真正支撑ResponseWriter的背后结构是非导出的http.response
  • 传递方式: ResponseWriter本质上也是一个指针,所以是按引用传递。
  • 方法
  • Write
    • 签名: Write([]byte) (int, error)
    • 功能: 接收一个byte切片作为参数,然后将它写入到HTTP响应的Body里面。
    • Content-Type检测: 如果在Write方法被调用时,header里面没有设定Content-Type,那么数据的前512字节会被用来检测Content-Type
  • WriteHeader
    • 签名: WriteHeader(int)
    • 功能: 接收一个整数类型(HTTP状态码)作为参数,并把它作为HTTP响应的状态码返回。
    • 隐式调用: 如果该方法没有显式调用,那么在第一次调用Write方法前,会隐式调用WriteHeader(http.StatusOK)
    • 用途: 主要用来发送错误类的HTTP状态码。
    • 限制: 调用完WriteHeader方法之后,仍然可以写入到ResponseWriter,但无法再修改header。
  • Header
    • 签名: Header() http.Header
    • 功能: 返回headers的map,可以进行修改。
    • 效果: 修改后的headers将会体现在返回给客户端的HTTP响应里。

内置的 Response

  • NotFound
  • 函数签名: func NotFound(w ResponseWriter, r *Request)
  • 功能: 包装一个404状态码和一个额外的信息,返回给客户端。
  • ServeFile
  • 函数签名: func ServeFile(w ResponseWriter, r *Request, name string)
  • 功能: 从文件系统提供文件,返回给请求者。
  • ServeContent
  • 函数签名: func ServeContent(w ResponseWriter, r *Request, name string, modtime time.Time, content io.ReadSeeker)
  • 功能:
    • 从文件系统提供文件,返回给请求者。
    • 可以处理Range请求(范围请求),如果只请求了资源的一部分内容,那么ServeContent可以如此响应,而ServeFile或者io.Copy则不行。
  • Redirect
  • 函数签名: func Redirect(w ResponseWriter, r *Request, url string, code int)
  • 功能: 告诉客户端重定向到另一个URL。

上一篇
下一篇