go语言web

 : jank    :   : 2867    : 2016-11-14 00:03  go

2016/11/02

1.web工作方式

1. http状态码

1XX 提示信息 - 表示请求已被成功接收,继续处理

2XX 成功 - 表示请求已被成功接收,理解,接受

3XX 重定向 - 要完成请求必须进行更进一步的处理

4XX 客户端错误 - 请求有语法错误或请求无法实现

5XX 服务器端错误 - 服务器未能实现合法的请求

2.第一次请求url,服务器端返回的是html页面,然后浏览器开始渲染HTML:当解析到HTML DOM里面的图片连接,css脚本和js脚本的链接,浏览器就会自动发起一个请求静态资源的HTTP请求,获取相对应的静态资源,然后浏览器就会渲染出来,最终将所有资源整合、渲染,完整展现在我们面前的屏幕上。

网页优化方面有一项措施是减少HTTP请求次数,就是把尽量多的css和js资源合并在一起,目的是尽量减少网页请求静态资源的次数,提高网页加载速度,同时减缓服务器的压力。


例:

package main
import (
    "fmt"
    "net/http"
    "strings"
    "log"
)
func sayhelloName(w http.ResponseWriter, r *http.Request) {
    r.ParseForm()  //解析参数,默认是不会解析的
    fmt.Println(r.Form)  //这些信息是输出到服务器端的打印信息
    fmt.Println("path", r.URL.Path)
    fmt.Println("scheme", r.URL.Scheme)
    fmt.Println(r.Form["url_long"])
    for k, v := range r.Form {
        fmt.Println("key:", k)
        fmt.Println("val:", strings.Join(v, ""))
    }
    fmt.Fprintf(w, "Hello astaxie!") //这个写入到w的是输出到客户端的
}
func main() {
    http.HandleFunc("/", sayhelloName) //设置访问的路由
    err := http.ListenAndServe(":9090", nil) //设置监听的端口
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

3.go的http包详解

Go的http有两个核心功能:Conn、ServeMux

4.go处理表单的输入

通过r.Form.Get()只能获取单个的值

package main
import (
    "fmt"
    "html/template"
    "log"
    "net/http"
    "regexp"
)
func login(w http.ResponseWriter, r *http.Request) {
    fmt.Println("method:", r.Method) //获取请求的方法
    r.ParseForm()
    if r.Method == "GET" {
        t, _ := template.ParseFiles("login.gtpl")
        log.Println("i love you and welcome you come to my life!") //打印日志信息
        log.Println(t.Execute(w, nil))
        fmt.Fprintf(w, "欢迎登陆!")
    } else {
        //请求的是登陆数据,那么执行登陆的逻辑判断
        fmt.Println("username:", r.Form["username"])
        fmt.Println("password:", r.Form["password"])
        if len(r.Form.Get("username")) > 0 && len(r.Form.Get("password")) > 0 {
            fmt.Println("姓名长度:", len(r.Form.Get("username")))//输出姓名长度
            fmt.Println("密码长度:", len(r.Form.Get("password")))//输出密码长度
            //正则匹配
            if m, _ := regexp.MatchString("^p{Han}+$", r.Form.Get("username")); !m {
                fmt.Fprintf(w, "请输入纯中文")
            }else{
                fmt.Fprintf(w, "姓名输入格式正确!")
            }
            if m, _ := regexp.MatchString("^[0-9]+$", r.Form.Get("password")); !m {
                fmt.Fprintf(w, "请输入纯数字!")
            }else{
                fmt.Fprintf(w, "密码格式正确!")
            }
            fmt.Fprintf(w, "欢迎" + r.Form["username"][0] + "登陆成功!!") //拼接字符串
            fmt.Println("username", template.HTMLEscapeString(r.Form.Get("username")))//转义输出
            template.HTMLEscape(w, []byte(r.Form.Get("username"))) //转义输出到客户端
        }
    }
}
func main() {
    //http.HandleFunc("/", sayhelloName)       //设置访问的路由
    http.HandleFunc("/login", login)         //设置访问的路由
    err := http.ListenAndServe(":9090", nil) //设置监听的端口
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}



5. go 上传文件

package main
import (
    "time"
    "crypto/md5"
    "fmt"
    "io"
    "net/http"
    "strconv"
    "html/template"
    "os"
    "log"
)
// 处理/upload 逻辑
func upload(w http.ResponseWriter, r *http.Request) {
    fmt.Println("method:", r.Method) //获取请求的方法
    if r.Method == "GET" {
    //引入上传页面,生成token
        crutime := time.Now().Unix()   //获取当前时间戳
        h := md5.New()   //创建一个md5对象
        io.WriteString(h, strconv.FormatInt(crutime, 10))
        token := fmt.Sprintf("%x", h.Sum(nil)) //返回填写后的结果, h.Sum(nil) 为[]byte类型
        t, _ := template.ParseFiles("login.gtpl")  //引入html
        t.Execute(w, token)  //执行
    } else {
        r.ParseMultipartForm(32 << 20) //服务端调用r.ParseMultipartForm,把上传的文件存储在内存和临时文件中
        file, handler, err := r.FormFile("uploadfile") //使用r.FormFile获取文件句柄,然后对文件进行存储等处理。
        if err != nil {
            fmt.Println(err)
            return
        }
        defer file.Close()
        fmt.Fprintf(w, "%v", handler.Header)  //web输出头信息
        f, err := os.OpenFile("./"+handler.Filename, os.O_WRONLY|os.O_CREATE, 0666)  //把上传的文件按原文件名写入当前目录
        if err != nil {
            fmt.Println(err)
            return
        }
        defer f.Close()
        io.Copy(f, file)
    }
}
func main() {
    //http.HandleFunc("/", sayhelloName)       //设置访问的路由
    http.HandleFunc("/upload", upload)         //设置访问的路由
    err := http.ListenAndServe(":9090", nil) //设置监听的端口
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}


2016/11/04

  go使用mysql数据库

1.访问数据库,Go没有内置的驱动支持任何的数据库,但是Go定义了database/sql接口,用户可以基于驱动接口开发相应数据库的驱动

2.database/sql接口

1. Go与PHP不同的地方是Go官方没有提供数据库驱动,而是为开发数据库驱动定义了一些标准接口,开发者可以根据定义的接口来开发相应的数据库驱动,这样做有一个好处,只要是按照标准接口开发的代码, 以后需要迁移数据库时,不需要任何修改。

2. 常用的mysql驱动有如下几种:

https://github.com/go-sql-driver/mysql //支持database/sql,全部采用go写。

https://github.com/ziutek/mymysql //支持database/sql,也支持自定义的接口,全部采用go写。

https://github.com/Philio/GoMySQL //不支持database/sql,自定义接口,全部采用go写。

1配置$GOPATH : 

   1.vim /etc/profile

   2.末尾添加:export GOPATH=/usr/local/go/bin  

   3.source /etc/profile

2获取mysql驱动:go get github.com/go-sql-driver/mysql

实例:

package main
import (
        _ "github.com/go-sql-driver/mysql"
        "database/sql"
        "fmt"
)
func main(){
    //连接数据库
    db, err := sql.Open("mysql", "root:***@/***?charset=utf8")
    checkErr(err)
    //插入数据
    stmt, err := db.Prepare("INSERT jank SET name=?,address=?,age=?,phone=?")
    checkErr(err)
    res, err := stmt.Exec("jank", "余干县", "21", 15727675874)
    checkErr(err)
    id, err := res.LastInsertId()
    checkErr(err)
    fmt.Println(id)
    //查询数据
    rows, err := db.Query("SELECT * FROM jank")
    checkErr(err)
    for rows.Next() {
        var id int
        var age int 
        var phone int
        var name string
        var address string
 
        err = rows.Scan(&id, &name, &address, &age, &phone)
        checkErr(err)
        fmt.Println(id)
        fmt.Println(name)
        fmt.Println(address)
        fmt.Println(age)
        fmt.Println(phone)
    }
    //更新数据
    stmt, err := db.Prepare("update jank set phone=? where id=?")
    checkErr(err)
    res, err := stmt.Exec(17777793319, 1)
    checkErr(err)
    affect, err := res.RowsAffected()
    checkErr(err)
    fmt.Println(affect)
    fmt.Println("--------------------------------")
    //删除数据
    stmt, err := db.Prepare(`DELETE FROM jank WHERE id=?`)
    checkErr(err)
    res, err := stmt.Exec(12)
    checkErr(err)
    num, err := res.RowsAffected()
    checkErr(err)
    fmt.Println(num)
}
func checkErr(err error) {
    if err != nil {
        panic(err)
    }
}

2016/11/08

一、go使用redis

1.String数据类型为字符串型,Byte数据类型为字节型。

一、String数据类型。

字符串型的变量,字符码范围为0到255,可以声明变长和定长字符串。

用“String*大小”的语法声明一个定长字符串。在VisualBasic中,文字字符串要用引号引起来。

二、Byte数据类型。

变量包含二进制数时,使用字节型。在转换格式期间,最好用字节型变量存储二进制数。

除了一元减法外,可以对整数进行处理的运算符均可处理字节型的数据类型。因为字节型是从0到255的无符号类型,所以不能表示负数。

2.例1:使用 "http://github.com/astaxie/goredis"包,调用redis

go get github.com/astaxie/goredis

package main
import(
    "github.com/astaxie/goredis"
    "fmt"
)
func main(){
    var client goredis.Client 
    //设置端口redis端口
    client.Addr = "127.0.0.1:6379"
    //字符串操作
    client.Set("a", []byte("jank"))
    val, _ := client.Get("a")
    fmt.Println(string(val))
    //client.Del("a")
    //链表操作
    janks := []string{"jank", "jack", "jason", "jacson"}
    for _, v :=range janks{
        client.Lpush("jank", []byte(v))
    }
    vals, _ := client.Lrange("jank", 0, 3)
    for _, vs := range vals {
        fmt.Println(string(vs))
    }
}

3.使用redigo扩展包

package main
import (  
    "fmt"  
    "github.com/garyburd/redigo/redis" 
    // "encoding/json" //json包 
    "reflect"
)  
func main(){
    //学习:http://blog.csdn.net/stevefang/article/details/38052121
    rs, err := redis.Dial("tcp", "127.0.0.1:6379")  //连接redis
    // 操作完后自动关闭  
    //defer rs.Close()  
    // 存json数据  
    // key := "aaa"  
    // imap := map[string]string{"key1": "111", "key2": "222"}  
    // // 将map转换成json数据  
    // value, _ := json.Marshal(imap)  
    // 取json数据  
    // // 先声明imap用来装数据  
    // var imap map[string]string  
    // key := "aaa"  
    // // json数据在go中是[]byte类型,所以此处用redis.Bytes转换  
    // value, err := redis.Bytes(rs.Do("GET", key))  
    // if err != nil {  
    //     fmt.Println(err)  
    // }  
    // // 将json解析成map类型  
    // errShal := json.Unmarshal(value, &imap)
    /*  
        若value的类型为int,则用redis.Int转换
        若value的类型为string,则用redis.String转换
        若value的类型为json,则用redis.Byte转换
    */
   //string
    rs.Do("SET", "age", 23)                         //存字符串
    age, err := redis.String(rs.Do("GET", "age"))   //取字符串
    fmt.Println(age)
    rs.Do("MSET", "names", "jank", "ages", "23")    //mset 存多个键值
    res, err := redis.Values(rs.Do("MGET", "names", "name", "ages", "age")) //取多个键值
    fmt.Println(reflect.TypeOf(res))  //结果为interface类型
    for _, val :=range res {
        fmt.Println(string(val.([]byte)))            
    }
    //list
    rs.Do("DEL", "from")
    vals := []string{"china", "jiangxi", "shangrao", "yugan", "santang", "songshan"}
    for _, val := range vals {
        rs.Do("LPUSH", "from", val)
    }
    //取出list数据,方法一
    vs, err := redis.Values(rs.Do("LRANGE", "from", 0, -1))
    for _, v :=range vs {
        fmt.Println(string(v.([]byte))) // 把[]byte型的v转换成string
    }
    //方法二
    var v1 string 
    var v2 string 
    var v3 string 
    var v4 string 
    var v5 string 
    redis.Scan(vs, &v1, &v2, &v3, &v4, &v5)
    fmt.Println(v1)
    fmt.Println(v2)
    fmt.Println(v3)
    fmt.Println(v4)
    fmt.Println(v5)
    //hush
    rs.Do("HSET", "school", "余干", "中学")
    school, err := redis.String(rs.Do("HGET", "school", "余干"))
    fmt.Println(school)
    rs.Do("HMSET", "school", "玉山", "一中", "上饶", "一中", "鄱阳", "一中")
    res, err := redis.Values(rs.Do("HMGET", "school", "余干", "玉山", "上饶", "鄱阳"))
    for _, v :=range res {
        fmt.Println(string(v.([]byte)))
    }
    // 若连接出错,则打印错误信息,返回  
    if err != nil {  
        fmt.Println(err)  
        return  
    }  
}

2016/11/10

1.go使用cookie

cookie的结构体:

type Cookie struct {
    Name       string
    Value      string
    Path       string
    Domain     string
    Expires    time.Time
    RawExpires string
    MaxAge   int
    Secure   bool
    HttpOnly bool
    Raw      string
    Unparsed []string // Raw text of unparsed attribute-value pairs
}

cookie操作:

package main
import(
    "fmt"
    "net/http"
    "html/template"
    "log"
)
//设置cookie
func cookie(w http.ResponseWriter, r *http.Request) {
    cookie := http.Cookie{Name: "name", Value: "jankai", Path: "/cookie", MaxAge: 3600}//设置cookie,cookie在"/cookie"路径下
    http.SetCookie(w, &cookie)
    t, _ := template.ParseFiles("cookie.gtpl")  //引入html
    log.Println("ok")
    log.Println(t.Execute(w, nil))
    w.Write([]byte("<b>欢迎!!</b>"))
}
//读取cookie
func rcookie(w http.ResponseWriter, r *http.Request) { 
    cookie, err := r.Cookie("name")
    if err == nil {        
        value := cookie.Value
        fmt.Fprintln(w,"当前cookie值为:" + value)  //输出在引入模板后
    }
}
//删除cookie
func dcookie(w http.ResponseWriter, r *http.Request) {
    cookie := http.Cookie{Name: "name", Path: "/", MaxAge: -1} //类似php设置cookie的生存期
    http.SetCookie(w, &cookie)
    _, err := r.Cookie("name")
    if err != nil {
        fmt.Fprintln(w, "cookie删除成功!")
    }else{
        fmt.Fprintln(w, "cookie删除失败!")
    }
}
func main(){
    http.HandleFunc("/cookie", cookie)
    http.HandleFunc("/rcookie", rcookie)
    http.HandleFunc("/dcookie", dcookie)
    http.ListenAndServe(":9090", nil)
}

2.go使用session

例:

package main
import (
    "fmt"
    "github.com/astaxie/session" //引用session包
    _ "github.com/astaxie/session/providers/memory"
    "log"
    "net/http"
)
var globalSessions *session.Manager //定义一个manager
//然后在init函数中初始化
func init() {
    //传递cookie方式
    //使用cookie
    //globalSessions, _ = session.NewManager("cookie", `{"cookieName":"gosessionid","enableSetCookie":false,"gclifetime":3600,"ProviderConfig":"{"cookieName":"gosessionid","securityKey":"beegocookiehashkey"}"}`)
    //使用文件
    //globalSessions, _ = session.NewManager("file",`{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"./tmp"}`)
    //使用 mysql
    //globalSessions, _ = session.NewManager("mysql", `{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"username:password@protocol(address)/dbname?param=value"}`)
    //使用redis
    //globalSessions, _ = session.NewManager("redis", `{"cookieName":"gosessionid","gclifetime":3600,"ProviderConfig":"127.0.0.1:6379,100,astaxie"}`)
    //使用内存
    globalSessions, _ = session.NewManager("memory", "gosessionid", 36) 
    go globalSessions.GC()
}
func sayhelloName(w http.ResponseWriter, r *http.Request) {
    sess := globalSessions.SessionStart(w, r)
    sessionval := sess.Get("usernames")
    if sessionval == nil {
        w.Write([]byte("session:username  is null<br/>"))
        sess.Set("usernames", "sessionval")
    } else {
        fmt.Fprintln(w, "session:username  is " + sessionval.(string))
    }
}
func main() {
    http.HandleFunc("/", sayhelloName)       //设置访问的路由
    err := http.ListenAndServe(":9090", nil) //设置监听的端口
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}


   

备案编号:赣ICP备15011386号

联系方式:qq:1150662577    邮箱:1150662577@qq.com