一, HTTP协议客户端实现

1, 使用http.NewRequest()方法

首先创建一个client(客户端)对象,其次创建一个request(请求)对象,最后使用client发生request。详情如下:

package main

import (
   "fmt"
   "net/http"
)

func main() {
   testHttpNewRequest()
}

func testHttpNewRequest() {
   // 创建一个客户端
   client := http.Client{}
   // 创建一个请求,请求方式既可以是GET,也可以是POST
   request, err := http.NewRequest("GET", "http://www.baidu.com/", nil)
   CheckErr(err)
   // 客户端发送请求
   cookName := &http.Cookie{Name: "username", Value: "JACK"}
   // 添加cookie
   request.AddCookie(cookName)
   response, err := client.Do(request)
   CheckErr(err)
   // 设置请求头
   request.Header.Set("Accept-Language", "zh-cn")
   defer response.Body.Close()
   // 查看请求头数据
   fmt.Printf("Header:%+v\n", request.Header)
   fmt.Printf("响应状态码:%v\n", response.StatusCode)
   // 操作数据
   if response.StatusCode == 200 {
      //data, err := ioutil.ReadAll(response.Body)
      fmt.Println("网络请求成功")
      CheckErr(err)
      //fmt.Println(string(data))
   } else {
      fmt.Println("网络请求失败", response.Status)
   }
}

// 检查错误
func CheckErr(err error) {
   defer func() {
      if ins, ok := recover().(error); ok {
         fmt.Println("程序出现异常: ", ins.Error())
      }
   }()
   if err != nil {
      panic(err)
   }
}

2, 使用client.Get()方法

这种方法一共两个步骤,先创建一个client(客户端)对象,然后使用client调用Get()方法

package main

import (
   "fmt"
   "net/http"
)

func main() {
   testClientGet()
}

func testClientGet() {
   // 创建客户端
   client := http.Client{}
   // 通过client去请求
   response, err := client.Get("http://www.baidu.com")
   CheckErr(err)
   fmt.Printf("响应状态码:%v\n", response.StatusCode)
   if response.StatusCode == 200 {
      fmt.Println("网络请求成功")
      defer response.Body.Close()
   }
}

// 检查错误
func CheckErr(err error) {
   defer func() {
      if ins, ok := recover().(error); ok {
         fmt.Println("程序出现异常: ", ins.Error())
      }
   }()
   if err != nil {
      panic(err)
   }
}

3, 使用client.Post()或client.PostForm()方法

这种方法也是两个步骤,先创建一个client(客户端)对象,然后使用client调用POST或PostForm()方法。其实client的Post()或PostForm()方法,就是对http.NewRequest()封装。

4, 使用http.Get()方法

这个方法只有一个步骤,http的Get()方法就是对DefaultClient.Get()封装。

package main

import (
   "fmt"
   "net/http"
)

func main() {
   testHttpGet()
}

func testHttpGet() {
   // 获取服务器的数据
   response, err := http.Get("http://www.baidu.com")
   CheckErr(err)
   fmt.Printf("响应状态码:%v\n", response.StatusCode)
   if response.StatusCode == 200 {
      defer response.Body.Close()
      fmt.Println("网络请求成功")
      CheckErr(err)
   } else {
      fmt.Println("请求失败", response.Status)
   }
}

// 检查错误
func CheckErr(err error) {
   defer func() {
      if ins, ok := recover().(error); ok {
         fmt.Println("程序出现异常: ", ins.Error())
      }
   }()
   if err != nil {
      panic(err)
   }
}

5, 使用http.Post()或http.PostForm()方法

http的Post()函数或PostForm就是对DefaultClient.Post()或DefaultClient.PostForm()的封装。这个方法也只有一个 步骤

package main

import (
   "fmt"
   "net/http"
   "net/url"
   "strings"
)

func main() {
   testHttpPost()
}

func testHttpPost() {
   // 构造参数
   data := url.Values{"City": {"上海"}}
   // 参数转化成body
   reader := strings.NewReader(data.Encode())
   // 发起Post请求MIME格式
   response, err := http.Post("http://wwww.weibo.com.cn/", "application/x-www-form-urlencoded", reader)
   CheckErr(err)
   fmt.Printf("响应状态码:%v\n", response.StatusCode)
   if response.StatusCode == 200 {
      // 操作响应数据
      defer response.Body.Close()
      fmt.Println("请求成功")
      CheckErr(err)
   } else {
      fmt.Println("请求失败", response.Status)
   }
}

// 检查错误
func CheckErr(err error) {
   defer func() {
      if ins, ok := recover().(error); ok {
         fmt.Println("程序出现异常: ", ins.Error())
      }
   }()
   if err != nil {
      panic(err)
   }
}

二, HTTP协议服务端实现

① 启动Web服务的几种方式

1, 使用http.FileServer()方法

http.FileServer()搭建的服务器只提供静态文件的访问。应为这种web服务只支持静态文件访问,所以称之为静态文件访问。

http.ListenAndServer()函数用来启动Web服务,绑定并监听http端口。其中第一个参数为监听地址,第二个参数表示提供文件访问服务的HTTP处理器Hander。

Handler是一个接口,其中只有ServeHTTP(http.ResponseWrite, *http.Request)这一个方法,只有实现了该方法,就自动实现Handler接口,具体声明如下所示

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

http.FileServer()正好可以返回Handler类型,也就是可以提供文件访问服务的HTTP处理器。

FileServer()的参数是FileSystem接口,可以使用http.Dir()来指定服务端文件所在的路径。如果该路径中存在index.html文件,则会有限显示html文件,否则会显示文件目录。

package main

import "net/http"

func main()  {
   testFileServer()
}
func testFileServer(){
   http.ListenAndServe(":2003", http.FileServer(http.Dir("/Users/jack_zhou/Documents")))
}

2, 使用http.HandleFunc()方法

http.HandleFunc()的作用是注册网络访问的路由。因为它采用的是默认路由分发人物方式,所以称为默认的多路由分发服务。

HandleFunc()的第一个参数是请求路径的匹配模式,第二个参数是一个函数类型,表示这个请求需要处理的事情。

作为服务器,随时会处理很多的请求,如果没有路由,就需要使用if else 或switch这样的分支语言进行判断,实在太辛苦。Go提供一个ServeMux()方法去分发任务。HandleFunc()其实就是直接将参数交给DefaultServeMux()来进行处理。

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

HandleFunc()是一个典型的函数式编程例子,而函数式编也是GO的特色
HandleFunc()的第二个参数其实就是Handler接口中的ServeHTTP()方法。所以这第二个参数其实就是实现了Handler接口的handler实例。

通过http.HandleFunc()注册网络路由时,http.ListenAndServer()的第二个参数为nil,这意味着服务端采用默认的http.DefauleServeMux进行分发处理。

package main

import (
   "fmt"
   "net/http"
)

func main() {
   // 绑定路径,触发对应方法
   http.HandleFunc("index", indexHandler)
   // 绑定端口
   // 第一个桉树为监听地址,第二个参数为服务端处理程序,通常为nil,这意味着服务端调用http.DefaultServeMux进行处理。
   err := http.ListenAndServe("localhost:3013", nil)
   fmt.Println(err)
}

func indexHandler(w http.ResponseWriter, r *http.Request) {
   fmt.Println("/index...")
   w.Write([]byte("首页"))
}

② 服务端获取客户请求的数据

1,Get方式传递参数

  • r.ParseForm(),返回error,判断是否解析传参时出错
  • r.Form属性,返回url.Values,他是map[string][]string类型。一般情况下,使用r.FormValue(key)方法更简洁简便
  • r.FormValue(key)方法可以根据客户端传参的key获取对应的值。
  • 其中r表示*http.Request类型,w表示http.ResponseWriter类型。

2,Post方式传递参数

Post传参分为两种情况

  • 普通表单请求(直接使用r.PostFormValue(key)方法,可以根据表单的name取到对应的传值。)
  • 文件上传请求(使用r.FormFile(key)方法,根据文件上传控件的name取到上传文件爱你的File和FileHeader对象,然后通过io的copy()操作实现文件上传。)

3,获取cookies中的值

Cookie是一个结构体,可以通过http.SetCookie()函数设置Cookie,通过r.Cookie()方法获取cookie

posted on 2020-04-03 22:07  人生苦短use,what?  阅读(176)  评论(0编辑  收藏  举报