zoukankan      html  css  js  c++  java
  • Go语言基础之19--web编程基础

    一、web编程基础

    1.1 web工作方式

     

    1.2 HTTP协议详解

     a、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/537.4 //浏览器信息

    Accept:text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 //客户

    端能接收的MIME

    Accept-Encoding:gzip,deflate,sdch //是否支持流压缩

    Accept-Charset:UTF-8,*;q=0.5 //客户端字符编码集

    //空行,用于分割请求头和消息体  

    //消息体,请求资源参数,例如POST传递的参数

    b、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包是分段发的

    Connection: keep-alive //保持连接状态

    Content-Length: 90 //主体内容长度

    //空行 用来分割消息头和主体 

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"... //消息体

    1.3 http Keep-Alive特性

    A. Keep-Alive用来保持连接

    B. Keep-Alive通过web服务器(nginx、httpd)进行设置,保持的时间

    1.4 web程序开发

    A. 标准包 “net/http”封装web服务相关功能

    B. 使用简单、性能媲美nginx。

    实例:

    package main
    
    import (
        "fmt"
        "log"
        "net/http"
        "strings"
    )
    
    func sayhelloName(w http.ResponseWriter, r *http.Request) { //第一个参数是一个接口,第二个参数是一个结构体(封装了一系列方法,比如:取post提交参数等),r是接受请求,w是返回给浏览器
        r.ParseForm()                       //解析参数,默认是不会解析的,如果是post请求(带表单参数),会进行解析
        fmt.Println(r.Form)                 //这些信息是输出到服务器端的打印信息,将表单打印出来
        fmt.Println("path", r.URL.Path)     //请求路径
        fmt.Println("scheme", r.URL.Scheme) //scheme是http还是https
        fmt.Println(r.Form["url_long"])     //传递了一个表单参数url_long
        for k, v := range r.Form {
            fmt.Println("key:", k)
            fmt.Println("val:", strings.Join(v, ""))
        }
        fmt.Fprintf(w, "Hello world!") //这个写入到w的是输出到客户端的
        //w这里是一个接口,接口的好处就体现在封装成一个接口的话,不论是返回文件或者图片或者html都可以通过接口进行返回,不用接口的话,你需要为每一种返回类型写函数。帮你更好理解
    
    }
    func main() {
        http.HandleFunc("/", sayhelloName)       //设置访问的路由,sayhelloName是函数类型的参数
        err := http.ListenAndServe(":9090", nil) //设置监听的端口
        if err != nil {
            log.Fatal("ListenAndServe: ", err)
        }
    }

     执行结果:

    浏览器端:

    实例:获取用户传递过来的参数

    package main
    
    import (
        "fmt"
        "net/http"
    )
    
    func greet(w http.ResponseWriter, r *http.Request) {
        word := r.FormValue("word")  //通过formvalue来获取用户传递过来参数
        fmt.Fprintf(w, "greet Hello World! word:%s", word)
    }
    
    func main() {
        http.HandleFunc("/index", greet)
        http.ListenAndServe(":8080", nil)
    }

     执行结果:

    浏览器端:

    1.5 Golang web服务工作方式

     图1:

    go底层源码就是我们上面图示的体现:

    绑定监听端口:

     

    进入服务阶段(死循环,所以不停服务):

    客户端来一个请求连接,就accept起一个,完了最后通过起一个协程来处理当前连接的这个请求。

    go语言里面网络编程模型很简单,就是过来一个连接,起一个goroutine去处理这个连接请求。如果是nginx、c++、c等就需要做一个异步的epoll处理模型,go就非常简单,源码就和上面一样,所以以后要写一个tcp服务器,将上面源码搬过去就可以用。

    图2为图1的精细化展示:

    二、表单提交

    A. html代码中通过<form> </form>括起来的区域,允许用户提交数据。

    B.  Go对于表单处理非常方便

    实例:

    目录结构:

    login.html:

    <html>
        <body>
            <form action="/user/login" method="POST">
                <div>
                    <span>用户名:</span><input name="username" >
                </div>
                <div>
                    <span>密码:</span><input name="password" >
                </div>
                <div>
                        <input type="submit" value="提交">
                </div>
            </form>
        </body>
    </html>
    login.html

     main.go

    package main
    
    import (
        "fmt"
        "io/ioutil"
        "log"
        "net/http"
    )
    
    func userLogin(w http.ResponseWriter, r *http.Request) {
        fmt.Printf("r.method:%s
    ", r.Method)
        if r.Method == "GET" { //如果是get直接返回请求页面
            data, err := ioutil.ReadFile("./login.html")
            if err != nil {
                http.Redirect(w, r, "/404.html", http.StatusNotFound)
                return
            }
    
            w.Write(data) //要把内容输出到浏览器
        } else if r.Method == "POST" {
            r.ParseForm()                       //解析表单
            username := r.FormValue("username") //和html文件要一一对应
            password := r.FormValue("password")
    
            if username == "admin" && password == "admin" {
                fmt.Fprintf(w, "login success")
            } else {
                fmt.Fprintf(w, "login failed")
            }
        }
    }
    
    func main() {
        http.HandleFunc("/user/login", userLogin)
        err := http.ListenAndServe(":9090", nil)
        if err != nil {
            log.Fatal("ListenAndServe: ", err)
        }
    }

     执行结果:

    浏览器进行测试:

    输入正确:

    输入错误:

    三、模板介绍与使用

    3.1 模板替换

    A. {{}}(模板变量)来包含需要在渲染时被替换的字段, {{.}}表示当前的对象(go源码传递过来的对象)。

    B. 通过{{.FieldName}}访问对象的属性。

    实例:

    目录结构:

    index.html

    <html>
        <body>
            <form action="/user/login" method="POST">
                <div>
                    <span>用户名:{{.Name}}</span>
                </div>
                <div>
                    <span>年龄:{{.Age}}</span>
                </div>
            </form>
        </body>
    </html>
    index.html

    main.go

    package main
    
    import (
        "fmt"
        "html/template"  //加载模板的包
        "net/http"
    )
    
    var (
        t *template.Template  //定义一个接收模板的全局变量
    )
    
    type User struct {
        Name string
        Age  int
    }
    
    func initTemplate() (err error) {
        t, err = template.ParseFiles("./index.html") //把模板加载进来 ,t是返回的实例
        if err != nil {
            fmt.Printf("load template failed,err:%v
    ", err)
            return
        }
        return
    }
    
    func handleUserInfo(w http.ResponseWriter, r *http.Request) {
        var user User = User{ //初始化  //可以传递任何类型的数据进去
            Name: "user01",
            Age:  10,
        }
    
        t.Execute(w, user)  //进行渲染,t对应的就是模板中的.
    }
    
    func main() {
    
        err := initTemplate()
        if err != nil {
            return
        }
    
        http.HandleFunc("/user/info", handleUserInfo)
        err = http.ListenAndServe(":8080", nil)
        if err != nil {
            fmt.Printf("listen failed, err:%v
    ", err)
            return
        }
    }

    执行结果:

    浏览器端:

    3.2 if判断

    比如说一个场景,大于18岁就弹出来一个红色图标,小于18岁就弹出一个灰色图标,我们就可以通过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>

    其它用法:

    1) not 非
    {{if not .condition}}
    {{end}}
    2) and 与
    {{if and .condition1 .condition2}}
    {{end}}
    3) or 或
    {{if or .condition1 .condition2}}
    {{end}}
    4) eq 等于
    {{if eq .var1 .var2}}
    {{end}}
    5) ne 不等于
    {{if ne .var1 .var2}}
    {{end}}
    6) lt 小于 (less than)
    {{if lt .var1 .var2}}
    {{end}}
    7) le 小于等于
    {{if le .var1 .var2}}
    {{end}}
    8) gt 大于
    {{if gt .var1 .var2}}
    {{end}}
    9) ge 大于等于
    {{if ge .var1 .var2}}
    {{end}}

      

    实例:

    index.html

    <html>
        <body>
            <form action="/user/login" method="POST">
                <div>
                    <span>用户名{{.Name}}</span>
                </div>
                <div>
                    <span>年龄:{{.Age}}</span>
                </div>
                {{if gt .Age 18}}
                <div>
                    <span>hello, old man</span>
                </div>
                {{else}}
                <div>
                    <span>hello, young man</span>
                </div>
                {{end}}
            </form>
        </body>
    </html>
    index.html

     main.go代码依然用的是模板替换的代码

    查看结果:

    解释:

    可以看到年龄小于18,所以传递过来是小于18分支的字符串。

    3.3 with语法

    当我们传递的是结构体,单层没问题,如果是想调用嵌套结构体的话,就会出问题,此时我们就需要用到with语法。

    模板:

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

     解释:

    {{.}}:双括号中的点就指的是with后面的变量Name

    实例:

    结构:

    index.html

    <html>
        <body>
            <form action="/user/login" method="POST">
                <div>
                    <span>用户名{{.Name}}</span>
                </div>
                <div>
                    <span>年龄:{{.Age}}</span>
                </div>
                {{if gt .Age 18}}
                <div>
                    <span>hello, old man</span>
                </div>
                {{else}}
                <div>
                    <span>hello, young man</span>
                </div>
                {{end}}
                {{with .Address}}
                <div>
                    <span>省:{{.Province}}</span>
                </div>
                <div>
                    <span>城市:{{.City}}</span>
                </div>
                <div>
                    <span>邮编:{{.Code}}</span>
                </div>
                {{end}}
            </form>
        </body>
    </html>
    index.html

    main.go

    package main
    
    import (
        "fmt"
        "html/template"
        "net/http"
    )
    
    var (
        t *template.Template
    )
    
    type Address struct {
        City     string
        Province string
        Code     string
    }
    
    type User struct {
        Name    string
        Age     int
        Address Address  //继承
    }
    
    func initTemplate() (err error) {
        t, err = template.ParseFiles("./index.html")
        if err != nil {
            fmt.Printf("load template failed,err:%v
    ", err)
            return
        }
        return
    }
    
    func handleUserInfo(w http.ResponseWriter, r *http.Request) {
        var user User = User{  //初始化
            Name: "user01",
            Age:  10,
            Address: Address{
                City:     "beijing",
                Province: "beijing",
                Code:     "10086",
            },
        }
    
        t.Execute(w, user)
    }
    
    func main() {
    
        err := initTemplate()
        if err != nil {
            return
        }
    
        http.HandleFunc("/user/info", handleUserInfo)
        err = http.ListenAndServe(":8080", nil)
        if err != nil {
            fmt.Printf("listen failed, err:%v
    ", err)
            return
        }
    }

     执行结果:

    浏览器端查看:

    3.4 循环

    传递过来的首先必须要是一个切片

    模板:

    <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>

     range . 这个点就是切片中的一个元素

    实例:

    目录结构:

    index.html

    <html>
        <body>
            <form action="/user/login" method="POST">
            {{range .}}
                <div>
                    <span>用户名{{.Name}}</span>
                </div>
                <div>
                    <span>年龄:{{.Age}}</span>
                </div>
                {{if gt .Age 18}}
                <div>
                    <span>hello, old man</span>
                </div>
                {{else}}
                <div>
                    <span>hello, young man</span>
                </div>
                {{end}}
                {{with .Address}}
                <div>
                    <span>省:{{.Province}}</span>
                </div>
                <div>
                    <span>城市:{{.City}}</span>
                </div>
                <div>
                    <span>邮编:{{.Code}}</span>
                </div>
                <hr>
                {{end}}
            {{end}}
            </form>
        </body>
    </html>
    index.html

    main.go

    package main
    
    import (
        "fmt"
        "html/template"
        "net/http"
    )
    
    var (
        t *template.Template
    )
    
    type Address struct {
        City     string
        Province string
        Code     string
    }
    
    type User struct {
        Name    string
        Age     int
        Address Address
    }
    
    func initTemplate() (err error) {
        t, err = template.ParseFiles("./index.html")
        if err != nil {
            fmt.Printf("load template failed,err:%v
    ", err)
            return
        }
        return
    }
    
    func handleUserInfo(w http.ResponseWriter, r *http.Request) {
        var users []*User
        for i := 0; i < 15; i++ {
            var user User = User{
                Name: "user01",
                Age:  10,
                Address: Address{
                    City:     "beijing",
                    Province: "beijing",
                    Code:     "10086",
                },
            }
            users = append(users, &user)
        }
    
        t.Execute(w, users) //传递一个切片过去
    }
    
    func main() {
    
        err := initTemplate()
        if err != nil {
            return
        }
    
        http.HandleFunc("/user/info", handleUserInfo)
        err = http.ListenAndServe(":8080", nil)
        if err != nil {
            fmt.Printf("listen failed, err:%v
    ", err)
            return
        }
    }

     执行结果:

    浏览器端:

  • 相关阅读:
    sscanf 与 ssprintf 用法 (转载--https://www.cnblogs.com/Anker/p/3351168.html)
    PYTHON网络爬虫与信息提取[信息的组织与提取](单元五)
    PYTHON网络爬虫与信息提取[BeautifulSoup](单元四)
    PYTHON网络爬虫与信息提取[网络爬虫协议](单元二)
    Python网络爬虫与信息提取[request库的应用](单元一)
    scikit-learn实现ebay数据分析 的随笔
    machine leanring 笔记 vectorization
    machine learning 笔记 normal equation
    machine leanring 笔记 octave命令笔记
    UVa 1354 天平难题 Mobile Computing
  • 原文地址:https://www.cnblogs.com/forever521Lee/p/9507372.html
Copyright © 2011-2022 走看看