• Go语言系列- http编程和mysql


    http编程

    一、Http协议

     1. 什么是协议?

      协议,是指通信的双方,在通信流程或内容格式上,共同遵守的标准。

     2. 什么是http协议?

      http协议,是互联网中最常见的网络通信标准。

     3. http协议的特点

      ①通信流程:断开式(无状态)

            断开式:http协议每次响应完成后,会断开与客户端的连接

            无状态:由于服务器断开了之前的连接,就无法知晓连接间的关系

      ②内容格式:消息头和消息体

    二、http编程概述

       HTTP(HyperText Transfer Protocol,超文本传输协议)是互联网上应用最为广泛的一种网络协议,定义了客户端和服务端之间请求和响应的传输标准。Go语言标准库内建提供了net/http包,涵盖了HTTP客户端和服务端的具体实现。使用net/http包,我们可以很方便地编写HTTP客户端或服务端的程序。

     特点:

    • a. Go原生支持http,import(“net/http”)

    • b. Go的http服务性能和nginx比较接近

    • c. 几行代码就可以实现一个web服务

    三、客户端与服务端

    1. 服务端

    package main
     
    import (
        "fmt"
        "net/http"
    )
     
    //w, 给客户端回复数据
    //r, 读取客户端发送的数据
    func HandConn(w http.ResponseWriter, r *http.Request) {
        fmt.Println("r.Method = ", r.Method)
        fmt.Println("r.URL = ", r.URL)
        fmt.Println("r.Header = ", r.Header)
        fmt.Println("r.Body = ", r.Body)
     
        w.Write([]byte("hello go")) //给客户端回复数据
    }
     
    func main() {
        //注册处理函数,用户连接,自动调用指定的处理函数
        http.HandleFunc("/", HandConn)
     
        //监听绑定
        http.ListenAndServe(":8000", nil)
    }
    
    package main
    
    import (
        "fmt"
        "net/http"
    )
    
    func Hello(w http.ResponseWriter, r *http.Request) {
        fmt.Println("r.Method = ", r.Method)
        fmt.Println("r.URL = ", r.URL)
        fmt.Println("r.Header = ", r.Header)
        fmt.Println("r.Body = ", r.Body)
        fmt.Println("handle hello")
        fmt.Fprintf(w, "hello ")
    }
    
    func login(w http.ResponseWriter, r *http.Request) {
        fmt.Println("handle login")
        fmt.Fprintf(w, "login ")
    }
    
    func history(w http.ResponseWriter, r *http.Request) {
        fmt.Println("handle history")
        fmt.Fprintf(w, "history ")
    }
    
    func main() {
        http.HandleFunc("/", Hello)
        http.HandleFunc("/user/login", login)
        http.HandleFunc("/user/history", history)
        err := http.ListenAndServe("0.0.0.0:8880", nil)
        if err != nil {
            fmt.Println("http listen failed")
        }
    }
    http_server.go

    2. 客户端

    package main
     
    import (
        "fmt"
        "net/http"
    )
     
    func main() {
        //resp, err := http.Get("http://www.baidu.com")
        resp, err := http.Get("http://127.0.0.1:8000")
        if err != nil {
            fmt.Println("http.Get err = ", err)
            return
        }
     
        defer resp.Body.Close()
     
        fmt.Println("Status = ", resp.Status)
        fmt.Println("StatusCode = ", resp.StatusCode)
        fmt.Println("Header = ", resp.Header)
        //fmt.Println("Body = ", resp.Body)
     
        buf := make([]byte, 4*1024)
        var tmp string
     
        for {
            n, err := resp.Body.Read(buf)
            if n == 0 {
                fmt.Println("read err = ", err)
                break
            }
            tmp += string(buf[:n])
        }
     
        //读取网页内容,打印出来
        fmt.Println("tmp = ", tmp)
    }
    
    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))
    }
    http_client.go

    四、http常见请求方法

    HTTP请求的方法:
    HTTP/1.1协议中共定义了八种方法(有时也叫“动作”),来表明Request-URL指定的资源不同的操作方式
    • 1、OPTIONS
    返回服务器针对特定资源所支持的HTTP请求方法,也可以利用向web服务器发送‘*’的请求来测试服务器的功能性
    • 2、HEAD
    向服务器索与GET请求相一致的响应,只不过响应体将不会被返回。这一方法可以再不必传输整个响应内容的情况下,就可以获取包含在响应小消息头中的元信息。
    • 3、GET
    向特定的资源发出请求。它本质就是发送一个请求来取得服务器上的某一资源。资源通过一组HTTP头和呈现数据(如HTML文本,或者图片或者视频等)返回给客户端。GET请求中,永远不会包含呈现数据。
    • 4、POST
    向指定资源提交数据进行处理请求(例如提交表单或者上传文件)。数据被包含在请求体中。POST请求可能会导致新的资源的建立和/或已有资源的修改。 Loadrunner中对应POST请求函数:web_submit_data,web_submit_form
    • 5、PUT
    向指定资源位置上传其最新内容
    • 6、DELETE
    请求服务器删除Request-URL所标识的资源
    • 7、TRACE
    回显服务器收到的请求,主要用于测试或诊断
    • 8、CONNECT
    HTTP/1.1协议中预留给能够将连接改为管道方式的代理服务器。

    注意:

    • 1)方法名称是区分大小写的,当某个请求所针对的资源不支持对应的请求方法的时候,服务器应当返回状态码405(Mothod Not Allowed);当服务器不认识或者不支持对应的请求方法时,应返回状态码501(Not Implemented)。
    • 2)HTTP服务器至少应该实现GET和HEAD/POST方法,其他方法都是可选的,此外除上述方法,特定的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
    常见状态码

    get 和 post区别

      区别:

        get请求无消息体,只能携带少量数据

        post请求有消息体,可以携带大量数据

      携带数据的方式:

        get请求将数据放在url地址中

        post请求将数据放在消息体中

    GET请求请提交的数据放置在HTTP请求协议头中,而POST提交的数据则放在实体数据中; 
    GET方式提交的数据最多只能有1024字节,而POST则没有此限制。 

    五、Head请求

    package main
    
    import (
    	"fmt"
    	"net/http"
    	"net"
    	"time"
    )
    
    var url = []string{
    	"http://www.baidu.com",
    	"http://google.com",
    	"http://taobao.com",
    }
    
    func main() {
    
    	for _, v := range url {
    		c := http.Client{
    			Transport: &http.Transport {
    				Dial:func(network, addr string) (net.Conn, error){
    					timeout := time.Second*2
    					return net.DialTimeout(network, addr, timeout)
    				},
    			},
    		}
    		resp, err := c.Head(v)
    		if err != nil {
    			fmt.Printf("head %s failed, err:%v
    ", v, err)
    			continue
    		}
    
    		fmt.Printf("head succ, status:%v
    ", resp.Status)
    	}
    }
    

     六、表单及panic处理

    package main
    
    import (
    	"io"
    	"log"
    	"net/http"
    )
    
    const form = `<html><body><form action="#" method="post" name="bar">
                        <input type="text" name="in"/>
                        <input type="text" name="in"/>
                         <input type="submit" value="Submit"/>
                 </form></body></html>`
    
    func SimpleServer(w http.ResponseWriter, request *http.Request) {
    	io.WriteString(w, "<h1>hello, world</h1>")
    	panic("test test")
    }
    
    func FormServer(w http.ResponseWriter, request *http.Request) {
    	w.Header().Set("Content-Type", "text/html")
    	switch request.Method {
    	case "GET":
    		io.WriteString(w, form)
    	case "POST":
    		request.ParseForm()
    		io.WriteString(w, request.Form["in"][1])
    		io.WriteString(w, "
    ")
    		io.WriteString(w, request.FormValue("in"))
    	}
    }
    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)
    	}
    }
    

     七、模板

      1. 替换 {{.字段名}}

    • if 判断
    • if 常见操作
    • {{.}}
    • {{with .Var}}... {{end}}

      2. 循环

      {{range.}}... {{end}}

    模板示例1:

    package main
    
    import (
        "fmt"
        "os"
        "text/template"
    )
    
    type Person struct {
        Name  string
        Title string
        age   string
    }
    
    func main() {
        t, err := template.ParseFiles("day10/template/index.html")
        if err != nil {
            fmt.Println("parse file err:", err)
            return
        }
        p := Person{Name: "Mary", age: "31", Title: "我的个人网站"}
        if err := t.Execute(os.Stdout, p); err != nil {
            fmt.Println("There was an error:", err.Error())
        }
    }
    main.go
    <html>
        <head>
            <title>{{.Title}}</title>
        </head>
        <body>
            <p> hello, {{.Name}}</p>
            <p> {{.}}</p>
        </body>
     </html>
    index.html
    <html>
        <head>
            <title>我的个人网站</title>
        </head>
        <body>
            <p> hello, Mary</p>
            <p> {Mary 我的个人网站 31}</p>
        </body>
    </html>
    模板示例2
    package main
    
    import (
        "fmt"
        "html/template"
        "io"
        "net/http"
    )
    
    var myTemplate *template.Template
    
    type Result struct {
        output string
    }
    
    func (p *Result) Write(b []byte) (n int, err error) {
        fmt.Println("called by template")
        p.output += string(b)
        return len(b), nil
    }
    
    type Person struct {
        Name  string
        Title string
        Age   int
    }
    
    func userInfo(w http.ResponseWriter, r *http.Request) {
        fmt.Println("handle hello")
        //fmt.Fprintf(w, "hello ")
        var arr []Person
        p := Person{Name: "Mary001", Age: 10, Title: "我的个人网站"}
        p1 := Person{Name: "Mary002", Age: 10, Title: "我的个人网站"}
        p2 := Person{Name: "Mary003", Age: 10, Title: "我的个人网站"}
        arr = append(arr, p)
        arr = append(arr, p1)
        arr = append(arr, p2)
    
        resultWriter := &Result{}
        io.WriteString(resultWriter, "hello world")
        err := myTemplate.Execute(w, arr)
        if err != nil {
            fmt.Println(err)
        }
        fmt.Println("template render data:", resultWriter.output)
        //myTemplate.Execute(w, p)
        //myTemplate.Execute(os.Stdout, p)
        //file, err := os.OpenFile("C:/test.log", os.O_CREATE|os.O_WRONLY, 0755)
        //if err != nil {
        //    fmt.Println("open failed err:", err)
        //    return
        //}
    
    }
    
    func initTemplate(filename string) (err error) {
        myTemplate, err = template.ParseFiles(filename)
        if err != nil {
            fmt.Println("parse file err:", err)
            return
        }
        return
    }
    
    func main() {
        initTemplate("day10/template_http/index.html")
        http.HandleFunc("/user/info", userInfo)
        err := http.ListenAndServe("0.0.0.0:8880", nil)
        if err != nil {
            fmt.Println("http listen failed")
        }
    }
    main.go
    <html>
        <head>
        </head>
        <body>
            <p>hello world</p>
            <table border="1">
            {{range .}}
                <tr>
                    <td>{{.Name}}</td> <td>{{.Age}}</td><td>{{.Title}}</td>
                </tr>
             {{end}}
            </table>
        </body>
    </html>
    index.html

    Mysql编程

    新建测试表

    CREATE TABLE person (
        user_id int primary key auto_increment,
        username varchar(260),
        sex varchar(260),
        email varchar(260)
    );
    
    CREATE TABLE place (
        country varchar(200),
        city varchar(200),
        telcode int
    )
    

    1. 连接mysql

    database, err := sqlx.Open("mysql", "root:@tcp(127.0.0.1:3306)/test")
    

    2. insert操作

    r, err := Db.Exec("insert into person(username, sex, email)values(?, ?, ?)", "stu001", "man", "stu01@qq.com")
    
    package main
    
    import (
        "fmt"
    
        _ "github.com/go-sql-driver/mysql"
        "github.com/jmoiron/sqlx"
    )
    
    type Person struct {
        UserId   int    `db:"user_id"`
        Username string `db:"username"`
        Sex      string `db:"sex"`
        Email    string `db:"email"`
    }
    
    type Place struct {
        Country string `db:"country"`
        City    string `db:"city"`
        TelCode int    `db:"telcode"`
    }
    
    var Db *sqlx.DB
    
    func init() {
        database, err := sqlx.Open("mysql", "root:0000@tcp(127.0.0.1:3306)/test")
        if err != nil {
            fmt.Println("open mysql failed,", err)
            return
        }
        Db = database
    }
    
    func main() {
        r, err := Db.Exec("insert into person(username, sex, email)values(?, ?, ?)", "stu001", "man", "stu01@qq.com")
        if err != nil {
            fmt.Println("exec failed, ", err)
            return
        }
        id, err := r.LastInsertId()
        if err != nil {
            fmt.Println("exec failed, ", err)
            return
        }
    
        fmt.Println("insert succ:", id)
    }
    mysql_insert

    3. select操作

    err := Db.Select(&person, "select user_id, username, sex, email from person where user_id=?", 1)
    
    package main
    
    import (
        "fmt"
    
        _ "github.com/go-sql-driver/mysql"
        "github.com/jmoiron/sqlx"
    )
    
    type Person struct {
        UserId   int    `db:"user_id"`
        Username string `db:"username"`
        Sex      string `db:"sex"`
        Email    string `db:"email"`
    }
    
    type Place struct {
        Country string `db:"country"`
        City    string `db:"city"`
        TelCode int    `db:"telcode"`
    }
    
    var Db *sqlx.DB
    
    func init() {
    
        database, err := sqlx.Open("mysql", "root:0000@tcp(127.0.0.1:3306)/test")
        if err != nil {
            fmt.Println("open mysql failed,", err)
            return
        }
    
        Db = database
    }
    
    func main() {
    
        var person []Person
        err := Db.Select(&person, "select user_id, username, sex, email from person where user_id=?", 1)
        if err != nil {
            fmt.Println("exec failed, ", err)
            return
        }
    
        fmt.Println("select succ:", person)
    }
    mysql_select

    4. update操作

    _, err := Db.Exec("update person set username=? where user_id=?", "stu0001", 1)
    
    package main
    
    import (
        "fmt"
    
        _ "github.com/go-sql-driver/mysql"
        "github.com/jmoiron/sqlx"
    )
    
    type Person struct {
        UserId   int    `db:"user_id"`
        Username string `db:"username"`
        Sex      string `db:"sex"`
        Email    string `db:"email"`
    }
    
    type Place struct {
        Country string `db:"country"`
        City    string `db:"city"`
        TelCode int    `db:"telcode"`
    }
    
    var Db *sqlx.DB
    
    func init() {
    
        database, err := sqlx.Open("mysql", "root:0000@tcp(127.0.0.1:3306)/test")
        if err != nil {
            fmt.Println("open mysql failed,", err)
            return
        }
    
        Db = database
    }
    
    func main() {
    
        _, err := Db.Exec("update person set username=? where user_id=?", "stu0003", 1)
        if err != nil {
            fmt.Println("exec failed, ", err)
            return
        }
    
    }
    mysql_update

    5. delete操作

    _, err := Db.Exec("delete from person where user_id=?", 1)
    package main
    
    import (
        "fmt"
    
        _ "github.com/go-sql-driver/mysql"
        "github.com/jmoiron/sqlx"
    )
    
    type Person struct {
        UserId   int    `db:"user_id"`
        Username string `db:"username"`
        Sex      string `db:"sex"`
        Email    string `db:"email"`
    }
    
    type Place struct {
        Country string `db:"country"`
        City    string `db:"city"`
        TelCode int    `db:"telcode"`
    }
    
    var Db *sqlx.DB
    
    func init() {
    
        database, err := sqlx.Open("mysql", "root:0000@tcp(127.0.0.1:3306)/test")
        if err != nil {
            fmt.Println("open mysql failed,", err)
            return
        }
    
        Db = database
    }
    
    func main() {
    
        _, err := Db.Exec("delete from person where user_id=?", 1)
        if err != nil {
            fmt.Println("exec failed, ", err)
            return
        }
    
        fmt.Println("delete succ")
    }
    mysql_delete
  • 相关阅读:
    SSRS 2012 创建ReportServer数据库失败: The RPC server is not listening. (Exception from HRESULT: 0x800706B3)
    关于SSIS包调用,把Execute out of Process 设成True后运行失败问题
    Mark:Insert, Update, and Delete Destination table with SSIS
    转SSIS 2012 pass values from child package to parent with project deployment model
    [转]SSIS Parameter和Variable的区别
    转SQL SERVER – SSIS Parameters in Parent-Child ETL Architectures – Notes from the Field #040
    简单的plsql to tsql ,游标拆解
    TSQL 根据表名生成UPDATE SELECT INSERT
    SPLIT CURSOR INTO ROWSET DML
    c/c++ tricks
  • 原文地址:https://www.cnblogs.com/zhangyafei/p/10993315.html
Copyright © 2020-2023  润新知