Go-Web(请求响应篇)

2020-11-17  本文已影响0人  秃头小公主

成功进入到了Go-Web开发的学习,个人感觉要是想快速上手,学完语法就可以看这个了,让后先不要直接学框架,很局限。就先开始简单的go-web,让后看到数据处理可以去看看gorm,基本上go-web就ok啦,来吧小秃头们,咱们继续肝~(文章适用于有go语言基础)
这一篇文章我们来说说与html的交互(我自己这么认为,不对就不对了),也就是说我们写代码来处理前端的那些事,一切响应的呈现会出现在前端。

——————————————————————————————————————

我会把我们比作控制器,前端就好比显示器,后台的数据就是需要展示的内容。我们需要经过这样的一个步骤:显示器(告诉我们需要什么)--->控制器(进行一些操作)--->显示器,其中控制器进行的一下操作就可能和数据库进行交互。下面我们来第一步:
在这里我们将熟悉使用GO语言的net/http标准库(就是import “net/http”)

1.接受请求(我们一步到位使用复用器,不用的编写放在最后)
当我们收到前端给我们的请求,这份请求先进入多路复用器让后找到相应的处理器(handler)进行处理之后响应给前端。吃栗子,上代码:

import (
    "encoding/json"
    "fmt"
    "github.com/gorilla/mux"
    "log"
    "net/http"
)

 func handler(w http.ResponseWriter,r *http.Request) {//这两个参数多眼熟啊,不需要介绍
    data:="mengyu"
    fmt.Printf("a")//这个会打印在你的goland里面
    json.NewEncoder(w).Encode(data)//简单来说就是data打印到页面上
                                   //json.NewEncoder(): io.writer 接口 json数据流的写 html显示
                                   //json.NewDecoder(): io.reader 接口 json数据流读
}
func main() {
    m:=mux.NewRouter() //来一个复用器
    m.HandleFunc("/",handler)//第一个参数:当输入地址后加/,让handler来处理(也就是上面的那个)
    ser:=&http.Server{
        Addr:"127.0.0.1:8000",//你需要输入的网址
        Handler: m,//什么使用的那个复用器(我感觉复用器也是一个handler)
    }
    log.Fatal(ser.ListenAndServe())//log.Fatal():1.打印输出内容 2.退出应用程序 3.defer函数不会执行
                                   //ListenAndServe():处理上面 端口监听、请求解析、路由分配、响应处理
}

完成上面的操作,就算我们的大方向搭建好了,这样你可以在你的handler里面处理一些操作等等(这个之后再说),当然我们也可以不使用复用器来搭建(这里鸽一下就不介绍了),下面我们来看一下handler的串联。对于handler有handler和handler函数这两个东西,我在这篇文章不做介绍,不懒我再写懒就继续鸽,这篇文章主要就是实用就完了(其实我感觉它俩差不多)吃栗子,上代码(handler串联):

func handler1(w http.ResponseWriter,r *http.Request)  {
    data:="mengyu"
    json.NewEncoder(w).Encode(data)
}

func handler2 (h http.HandlerFunc) http.HandlerFunc {
    return func(writer http.ResponseWriter, request *http.Request) {//这就是返回一个handler
        h(writer,request)
    }
}

func main(){
    m:=mux.NewRouter()
    m.HandleFunc("/",handler2(handler1))//串完之后从handler2再进入handler1
    ser:=&http.Server{
        Addr: "127.0.0.1:8000",
        Handler: m,
    }
    log.Fatal(ser.ListenAndServe())
}

以上就酱~,来看下一步

2.处理请求

一般遇到请求的就是,提交表单啊,上传文件什么的。来直接看怎么处理,理论啥的自行解决(来自实习生简单粗暴的怒吼)
(1)表单提交

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body><!--我们现拥有一个表单-->
<form action="//127.0.0.1:8000/hello?hello=world&thread=123"  method="post"
      enctype="application/x-www-form-urlencoded"><!--enctype:支持的编码方式,这种编码方式会把数据编码为一个连续的“长查询字符串”-->
    <input type="text" name="hello" value="mengyu">
    <input type="text" name="post" value="456">
    <input type="submit">
</form>
</body>
</html>
func handler(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()//对请求进行语法分析
    fmt.Fprintln(w,r.Form)//r.Form:包含所有请求的参数
}
func main() {
    m:=mux.NewRouter()
    m.HandleFunc("/",handler)
    ser:=&http.Server{
        Addr: "127.0.0.1:8000",
        Handler: m,
    }
    log.Fatal(ser.ListenAndServe())
}

(2)文件上传

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="//127.0.0.1:8000/hello?hello=world&thread=123" method="post"
      enctype="multipart/form-data"><!--这里enctype发生改变-->
    <input type="text" name="hello" value="mengyu">
    <input type="text" name="post" value="456">
    <input type="file" name="uploaded"><!--增加上传按钮-->
    <input type="submit">
</form>
</body>
</html>
func process(w http.ResponseWriter, r *http.Request) {
    file,_,err:=r.FormFile("uploaded") //FormFile():返回所提供表单的密钥的第一个文件
    if err==nil{
        data,err:=ioutil.ReadAll(file) //ReadAll():读取,直到出现错误或EOF,返回读取的数据
        if err==nil{
            fmt.Fprintln(w,string(data))
        }
    }
}

func main() {
    m:=mux.NewRouter()
    m.HandleFunc("/hello",hello)
    ser:=&http.Server{
        Addr: "127.0.0.1:8000",
        Handler: m,
    }
    log.Fatal(ser.ListenAndServe())
}

3.发送响应
直接吃点栗子
(1)用Write方法向客户端发送响应
HELLO会展示再html页面上

import (
    "github.com/gorilla/mux"
    "log"
    "net/http"
)

func writeExample(w http.ResponseWriter, r *http.Request) {
    str:="HELLO"
w.Write([]byte(str))
}

func main(){
    m:=mux.NewRouter()
    m.HandleFunc("/write",writeExample)
    ser:=&http.Server{
        Addr: "127.0.0.1:8000",
        Handler: m,
    }
    log.Fatal(ser.ListenAndServe())
}

(2)通过WriteHeader方法写状态
再写一个handler

func writeHeadExample(w http.ResponseWriter, r *http.Request) {
    w.WriteHeader(501)
    fmt.Fprintln(w,"ERROR:501")
}

再main中加入声明

m.HandleFunc("/writehead" ,writeHeadExample)

(3)通过编写首部实现客户端的重定向
再来一个handler

func headerExample(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Location" ,"https://www.jianshu.com" )//重定向到简书
    w.WriteHeader(302)//设置状态码
}

main中声明一下

m.HandleFunc("/redirect" ,headerExample)

4.Cookie
肯定有疑问,为什么这里放这么一个东西,这个东西干嘛的,来我们从头说~

(1)将cookie发送到浏览器(将cookie存储到客户端)

func setCookie(w http.ResponseWriter,r *http.Request)  {
    c1:=http.Cookie{
        Name: "first_cookie",
        Value: "Go Web1",
        HttpOnly: true,
    }
    c2:=http.Cookie{
        Name:     "second_cookie",
        Value:    "Go Web2",
        HttpOnly: true,
    }
    http.SetCookie(w,&c1)//使用setCookie方法设置cookie
    http.SetCookie(w,&c2)

}

func main(){
    m:=mux.NewRouter()
    m.HandleFunc("/set_cookie",setCookie)
    ser:=&http.Server{
        Addr: "127.0.0.1:8000",
        Handler: m,
    }
    log.Fatal(ser.ListenAndServe())
}

(2)从浏览器获取cookie
加个handler

func getCookie(w http.ResponseWriter,r *http.Request)  {
    h:=r.Header["Cookie"]//先返回一个切片,切片中包含一个字符串,字符串中包含了好多cookie,
                         //让后再取得单独键值对格式cookie,这是一种很麻烦的方法来获取cookie
    fmt.Fprintln(w,h)
}

在main声明一下

m.HandleFunc("/get_cookie",getCookie)

我们来换一个简单的方法来获取cookie

func getCookie(w http.ResponseWriter,r *http.Request)  {
    c1,err:=r.Cookie("first_cookie")//获取单个cookie
    if err!=nil{
        fmt.Fprintln(w,"error,don't get first_cookie")
    }
    cs:=r.Cookies()//获取所有的cookie
    fmt.Fprintln(w,c1)
    fmt.Fprintln(w,cs)
}

(3)cookie的应用——闪现消息
搜索网址出hello,刷新hello不见了~

import (
    "encoding/base64"
    "fmt"
    "github.com/gorilla/mux"
    "log"
    "net/http"
    "time"
)

func setMessage(w http.ResponseWriter,r *http.Request)  {
    msg:=[]byte("Hello")
    c:=http.Cookie{
        Name: "flash",
        Value: base64.URLEncoding.EncodeToString(msg),//对消息使用base64url编码,
         //(如果cookie的值没有“%” “ ”等特殊字符可以不编码),闪现消息本身会包含空格啥的,就得编码了
    }
    http.SetCookie(w,&c)
}
func showMessage(w http.ResponseWriter,r *http.Request)  {
    c,err:=r.Cookie("flash" )
    if err!= nil{//如果没有找到cookie
        if err == http.ErrNoCookie{
            fmt.Fprintln(w,"no message found!!!")  //把err变成一个http.ErrNoCookie值,并返回
                                              
        }
    }else {//如果找到了这个cookie
        rc:=http.Cookie{ //创建一同名cookie
            Name: "flash",
            MaxAge: -1, //设置过期时间(被浏览器创建之后存活多少秒)
            Expires: time.Unix(1,0),//设置过期时间为过去的时间(准确设置过期时间)
        }
        http.SetCookie(w,&rc)
        val,_:=base64.URLEncoding.DecodeString(c.Value)
        fmt.Fprintln(w,string(val))
    }
}
func main() {
    m:=mux.NewRouter()
    m.HandleFunc("/set_message",setMessage)
    m.HandleFunc("/show_message",showMessage)
    ser:=&http.Server{
        Addr: "127.0.0.1:8000",
        Handler: m,
    }
    log.Fatal(ser.ListenAndServe())
}
上一篇 下一篇

猜你喜欢

热点阅读