zoukankan      html  css  js  c++  java
  • http编程

    一、HTTP

    1.http编程(http是文本协议,socket是二进制协议)
       a.Go原生支持http,import(“net/http”)
       b.Go的http服务性能和nginx 比较接近
       c. 几行代码就可以实现 一个web服务

    http请求包

    GET /domains/example/ HTTP/1.1    //请求行: 请求方法 请求URI HTTP协议/协议版本
    Host:www.iana.org    //服务端的主机名
    User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.4 (KHTML, like Gecko) Chrome/22.0.1229.94 Safari/
    //浏览器 信息
    Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8    //客户端能接收的mine
    Accept-Encoding:gzip,deflate,sdch    //是否支持流压缩
    Accept-Charset:UTF-8,*;q=0.5    //客户端字符编码集
    //空行, 用于分割请求头和消息体
    //消息体,请求资源参数,例如POST传递的参数

    http响应包

    HTTP/1.1 200 OK    //状态行                
    Server: nginx/1.0.8    //服务器使用的WEB软件名及版本
    Date:Date: Tue, 30 Oct 2012 04:14:25 GMT    //发送时间        
    Content-Type: text/html    //服务器发送信息的类型    
    Transfer-Encoding: chunked    //表示发送HTTP包是分段发的,http/1.0是全部一起发,http/1.1是一段一段的发    
    Connection: keep-alive    //保持连接状态    
    Content-Length: 90    //主体内容长度    
    //空行用来分割消息头和主体
    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"... //消息体

    发送http请求

    package main
    
    import (
        "fmt"
        "io"
        "net"
    )
    
    func main() {
        conn, err := net.Dial("tcp", "www.baidu.com:80")
        if err != nil {
            fmt.Println("Error dialing", err.Error())
            return
        }
        defer conn.Close()
        msg := "GET / HTTP/1.1
    "
        msg += "Host: www.baidu.com
    "
        msg += "Connection: close
    "
        msg += "
    
    "
        _, err = io.WriteString(conn, msg)
        if err != nil {
            fmt.Println("write string failed, ", err)
            return
        }
        buf := make([]byte, 4096)
        for {
            count, err := conn.Read(buf)
            if err != nil {
                    break
            }
            fmt.Println(string(buf[0:count]))
        }
    }
    View Code

    HTTP服务端

    package main
    
    import (
        "fmt"
        "net/http"
    )
    
    func Hello(w http.ResponseWriter, r *http.Request) { 
        //r  是请求头信息
        fmt.Println("handle hello")
        fmt.Fprintf(w, "hello ")  //将数据返回给客户端
    }
    
    func main() {
    
        http.HandleFunc("/", Hello)
        err := http.ListenAndServe("0.0.0.0:8880", nil) //检测端口,解析请求,分发请求进行处理
        if err != nil {
            fmt.Println("http listen failed")
        }
    }

    HTTP客户端

    package main
    
    import (
        "fmt"
        "io/ioutil"
        "net/http"
    )
    
    func main() {
    
        res, err := http.Get("https://www.baidu.com/")
        if err != nil {
            fmt.Println("get err:", err)
            return
        }
        data, err := ioutil.ReadAll(res.Body)  //读取网络链接里面数据
        if err != nil {
            fmt.Println("get data err:", err)
            return
        }
        fmt.Println(string(data))
    }

    2.http常见请求方法

      1)Get请求

      2)Post请求

      3)Put请求

      4)Delete请求

      5)Head请求

    Head请求头

    package main
    
    import (
        "fmt"
        "net/http"
    )
    
    var url = []string{
        "http://www.baidu.com",
        "http://google.com",
        "http://taobao.com",
    }
    
    func main() {
        for _, v := range url {
            resp, err := http.Head(v)  //Head请求时只会返回响应头
            if err != nil {
                fmt.Printf("head %s failed, err:%v
    ", v, err)
                continue
            }
            fmt.Printf("head succ, status:%v
    ", resp.Status)
        }
    }
    View Code

    3.http 常见状态码

    http.StatusContinue = 100   //继续访问
    http.StatusOK = 200
    http.StatusFound = 302        //跳转
    http.StatusBadRequest = 400    //发送的请求,协议格式不对
    http.StatusUnauthorized =401    //没有授权
    http.StatusForbidden = 403        //没有权限访问
    http.StatusNotFound = 404        //请求地址不存在
    http.StatusInternalServerError = 500    //服务器有问题
    502  //有代理,后端服务挂了
    504  //后端处理请求超时

    4、表单处理

    package main
    
    import (
        "io"
        "net/http"
    )
    const form =`<html><meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
                <body><form action="#" method="post" name="bar">
                <div> 姓名:<input type="text" name="username1"/></div>
                <div> 密码:<input type="text" name="password"/></div>
                <input type="submit" value="登录"/>
                </form></html></body>`
    func SimpleServer(w http.ResponseWriter, request *http.Request) {
        io.WriteString(w, "<h1>hello, world</h1>")  //返回h1标签至前端渲染
    }
    func FormServer(w http.ResponseWriter, request *http.Request) {
        w.Header().Set("Content-Type", "text/html")  //设置响应头
        w.Header().Set("Server", "Go 1.9.2 Server")
        w.Header().Set("Niubi", "hahahaha")
        switch request.Method {
            case "GET":
            io.WriteString(w, form)
            case "POST":
            request.ParseForm()   //解析post请求,才能得到请求内容
            io.WriteString(w, request.Form["username"][0])  //go支持文本框name相同
            io.WriteString(w, "
    ")
            io.WriteString(w, request.FormValue("username"))//取不到内容返回空
        }
    }
    
    func main() {
        http.HandleFunc("/test1", SimpleServer)
        http.HandleFunc("/test2", FormServer)
        if err := http.ListenAndServe(":8088", nil); err != nil {
            
        }
    }
    View Code

    5、panic处理

    package main
    
    import (
        "io"
        "net/http"
        "log"
    )
    
    const form = `<html>
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> 
    <body><form action="#" method="post" name="bar">
    <div> 姓名:<input type="text" name="username1"/></div>
    <div> 密码:<input type="text" name="password"/></div>
    <input type="submit" value="登录"/>
    </form></html></body>`
    
    func SimpleServer(w http.ResponseWriter, request *http.Request) {
        io.WriteString(w, "<h1>hello, world</h1>")
    }
    func FormServer(w http.ResponseWriter, request *http.Request) {
        w.Header().Set("Content-Type", "text/html")
        w.Header().Set("Server", "Go 1.9.2 Server")
        w.Header().Set("Niubi", "hahahaha")
    
        var p *int
        *p = 10   //出现panic,go自动处理了异常,线程挂掉,但是进程不会挂掉
        switch request.Method {
        case "GET":
            io.WriteString(w, form)
        case "POST":
            request.ParseForm()
            io.WriteString(w, request.FormValue("username"))
            io.WriteString(w, "
    ")
            io.WriteString(w, request.FormValue("password"))
        }
    }
    func main() {
        http.HandleFunc("/test1", logPanics(SimpleServer)
        http.HandleFunc("/test2", logPanics(FormServer))
        if err := http.ListenAndServe(":8088", nil); err != nil {
        }
    }
    
    func logPanics(handle http.HandlerFunc) http.HandlerFunc {
        return func(writer http.ResponseWriter, request *http.Request) {//返回匿名函数,原型和处理函数一致
            defer func() {
                if x := recover(); x != nil {
                    log.Printf("[%v] caught panic: %v", request.RemoteAddr, x) //捕获错误
                }
            }()
            handle(writer, request)  //执行处理函数
        }
    }
    View Code

    二、模板的使用

    1、渲染到终端

    模板文件index.html

    <html>
        <head>
        </head>
        <body>
            {{if gt .Age 18}}  //gt大于, .指后端传过来的数据集
                <p>hello, old man, {{.Name}}</p>
            {{else}}
                <p>hello,young man, {{.Name}}</p>
            {{end}}
        </body>
    </html>
    package main
    
    import (
        "fmt"
        "os"
        "text/template"  
    ) type Person struct { Name string Age string } func main() { t, err := template.ParseFiles("./index.html") //加载模板 if err != nil { fmt.Println("parse file err:", err) return } p := Person{Name: "Mary", Age: "31"} if err := t.Execute(os.Stdout, p); err != nil{ fmt.Println("There was an error:", err.Error()) } }

    2、渲染到前端

    index2.html

    <html>
        <head>
        </head>
        <body>    
            <p>hello, old man, {{.age}}</p>  
        </body>
     </html>
    package main
    
    import (
        "fmt"    
        "text/template"
        "net/http"
    )
    
    type Person struct {
        Name string
        Age  int
    }
    
    var (
        gtemp *template.Template
    )
    
    func init() {
        t, err := template.ParseFiles("./index2.html")
        if err != nil {
            fmt.Println("parse file err:", err)
            return
        }
        gtemp = t
    }
    
    func handleUserInfo(w http.ResponseWriter, r *http.Request) {
        p := &Person{
            Name:"mary", 
            Age: 20,
        }
        //执行模板渲染
        gtemp.Execute(w, p)
    }
    
    func main() {
        
        http.HandleFunc("/user_info", handleUserInfo)
        http.ListenAndServe(":8080", nil)
    }

    三、模板语句

    1)if判断

    <html>
        <head>
        </head>
        <body>
            {{if gt .Age 18}}
                <p>hello, old man, {{.Name}}</p>
            {{else}}
                <p>hello,young man, {{.Name}}</p>
            {{end}}
        </body>
    </html>

    2if常见操作符

    not     非
    {{if not .condition}} 
    {{end}}
    
    and    与
    {{if and .condition1 .condition2}} 
    {{end}}
    
    or    或
    {{if or .condition1 .condition2}}
    {{end}}
    
    eq    等于
    {{if eq .var1 .var2}}
    {{end}}
    
    ne    不等于
    {{if ne .var1 .var2}}
    {{end}}
    
    lt     小于 (less than)
    {{if lt .var1 .var2}}
    {{end}}
    
    le     小于等于
    {{if le .var1 .var2}} 
    {{end}}
    
    gt     大于
    {{if gt .var1 .var2}}
    {{end}}
    
    
    ge     大于等于
    {{if ge .var1 .var2}}
    {{end}}
    View Code

    3){{.}}

    后端传过来的结构体或者map,都是.xx提取数据

    <html>
        <head>
        </head>
        <body>
            <p>hello, old man, {{.}}</p>
        </body>
    </html>

    4){{with .Var}}

    <html>
        <head>
        </head>
        <body>
            {{with .Name}}
                <p>hello, old man, {{.}}</p>   //.代表Name的值
            {{end}}
        </body>
    
    </html>

    5)循环

    <html>
        <head>
        </head>
        <body>
            {{range .}}
                {{if gt .Age 18}}
                    <p>hello, old man, {{.Name}}</p>
                {{else}}
                    <p>hello,young man, {{.Name}}</p>
                {{end}}
            {{end}}
        </body>
    </html>
    <html>
    <head>
    </head>
    <body>
    <table border="1px">
    {{range .}}
        <tr>
        {{if gt .Age 18}}
        <td> {{.Name}}</td>
        <td> {{.Age}}</td>       
        {{else}}
        <td> {{.Name}}</td>
        <td> {{.Age}}</td>       
        {{end}}
        </tr>
    {{end}}
    </table>
    </body>
    </html>
    index.html
    package main
    
    import (
        "fmt"
        "text/template"
        "net/http"
    )
    
    type Person struct {
        Name string
        Age  int
    }
    
    var (
        gtemp *template.Template
    )
    
    func init() {
        t, err := template.ParseFiles("./index.html")
        if err != nil {
            fmt.Println("parse file err:", err)
            return
        }
        gtemp = t
    }
    
    func handleUserInfo(w http.ResponseWriter, r *http.Request) {
        
        var persons []*Person
        for i := 0; i < 10; i++{
            p := &Person{
                Name: fmt.Sprintf("stu%d", i),
                Age: i*10,
            }
    
            persons = append(persons, p)
        }
    
        //执行模板渲染
        gtemp.Execute(w, persons)
    }
    
    func main() {
        
        http.HandleFunc("/user_info", handleUserInfo)
        http.ListenAndServe(":8080", nil)
    }
    main.go


    四、静态文件服务器

    文件服务器

    package main
    
    import (    
        "net/http"
    )
    func main() {
        
        http.Handle("/", http.FileServer(http.Dir("./"))
        //http.Handle("/static/", http.FileServer(http.Dir("./static/")))    // '/static/'路径默认会加在./static/后面,需要将文件放在/static//static/下面
        http.Handle("/media/", http.StripPrefix("/media/", http.FileServer(http.Dir("./media/")))) //去掉默认加在url  /media/
        http.ListenAndServe(":8080", nil)
    }

    http模板渲染展示

    package main
    
    import (
        "fmt"    
        "html/template"
        "net/http"
    )
    
    var (
        gtemp *template.Template
    )
    
    func init() {
        t, err := template.ParseFiles("./views/index.html")
        if err != nil {
            fmt.Println("parse file err:", err)
            return
        }
        gtemp = t
    }
    
    func handleIndex(w http.ResponseWriter, r *http.Request) {
        gtemp.Execute(w, nil)
    }
    
    func main() {
    
        http.HandleFunc("/index", handleIndex)
        //http.Handle("/static/", http.FileServer(http.Dir("./static/")))    // '/static/'路径默认会加在./static/后面,需要将文件放在/static//static/下面
        http.Handle("/media/", http.StripPrefix("/media/", http.FileServer(http.Dir("./media/")))) //去掉默认加在url  /media/
        http.ListenAndServe(":8080", nil)
    }
    mian.go
  • 相关阅读:
    自主学习之RxSwift(一) -----Driver
    RxSwift:ReactiveX for Swift 翻译
    C简单实现动态顺序表
    C简单实现双向链表
    C实现单链表
    享受这一点点的平淡
    C文件读写
    大神都在看的RxSwift 的完全入坑手册
    字符串常量存在何处
    认识自己
  • 原文地址:https://www.cnblogs.com/domestique/p/8443754.html
Copyright © 2011-2022 走看看