http请求
hello world
package main import ( "fmt" "net/http" ) //创建处理器函数 func handler(w http.ResponseWriter,r *http.Request){ //r.URL.Path路由中的参数 fmt.Fprintln(w,"世界 你好",r.URL.Path) } func main(){ //创建多路复用器 mux:=http.NewServeMux() mux.HandleFunc("/",handler) //创建路由 http.ListenAndServe(":8080",mux) }
web服务器的创建
使用默认的多路复用器(DefaultServeMux)
1.使用处理器函数处理请求
package main import ( "fmt" "net/http" ) //使用默认的多路服用器 //1.使用处理器函数处理请求 //创建处理器函数 func handler(w http.ResponseWriter,r *http.Request){ fmt.Fprintln(w,"正在通过处理器函数处理您的请求") } func main(){ http.HandleFunc("/",handler) http.ListenAndServe(":8080",nil) }
2.使用处理器处理请求
package main import ( "fmt" "net/http" ) //2.使用处理器处理请求 type MyHandler struct{} func (h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "正在通过处理器处理您的请求") } func main() { myHandler := MyHandler{} //调用处理器 http.Handle("/", &myHandler) http.ListenAndServe(":8080", nil) }
3.测试通过Server结构详细配置服务器
package main import ( "fmt" "net/http" "time" ) //通过Server结构对服务器进行更详细的配置 type MyHandler struct{} func (h *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "测试通过Server结构详细配置服务器") } func main() { myHandler := MyHandler{} //通过Server结构对服务器进行更详细的配置 server := http.Server{ Addr: ":8080", Handler: &myHandler, ReadTimeout: 2 * time.Second, } server.ListenAndServe() }
使用自己创建的多路复用器
package main import ( "fmt" "net/http" ) //使用自己创建的多路复用器 func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "通过自己创建的多路复用器来处理请求") } func main() { mux := http.NewServeMux() mux.HandleFunc("/myMux", handler) http.ListenAndServe(":8080", mux) }
数据库
model/user.go
package model import ( "fmt" "gotest/web02_db/utils" ) //user结构体 type User struct { ID int Username string Password string Email string } //AddUser 添加User的方法一 func (user *User) AddUser1() error { //1.写sql语句 sqlStr := "insert into users(username,password,email) values(?,?,?)" //2.预编译 inStmt, err := utils.Db.Prepare(sqlStr) if err != nil { fmt.Println("预编译出现异常:", err) return err } //3.执行 _, err2 := inStmt.Exec("admin", "123456", "admin@123.com") if err2 != nil { fmt.Println("执行出现异常:", err2) return err } return nil } //AddUser2 天机user的方法2 func (user *User) AddUser2() error { //1.写sql语句 sqlStr := "insert into users(username,password,email) values(?,?,?)" //2.执行 _, err := utils.Db.Exec(sqlStr, "admin2", "666666", "admin2@sina.com") if err != nil { fmt.Println("执行出现异常:", err) return err } return nil } func (user *User) AddUser() error { //写sql语句 sqlStr := "insert into users(username,password,email) values(?,?,?)" //预编译 stmt, err := utils.Db.Prepare(sqlStr) if err != nil { fmt.Println("预编译出现异常:", err) return err } //执行 _, erro := stmt.Exec(user.Username, user.Password, user.Email) if erro != nil { fmt.Println("执行出现异常:", erro) return erro } return nil } //获取一条记录 func (user *User) GetUserByID(userId int) (*User, error) { //写sql语句 sqlStr := "select id,username,password,email from users where id=?" //执行sql row := utils.Db.QueryRow(sqlStr, userId) //声明三个变量 var username string var password string var email string //将各个字段中的值读取到以上三个变量中 err := row.Scan(&userId, &username, &password, &email) if err != nil { return nil, err } //将三个变量的值赋给User结构体 u := &User{ ID: userId, Username: username, Password: password, Email: email, } return u, nil } //获取多条记录 func (user *User) GetUsers() ([]*User, error) { //写sql语句 sqlStr := "select id,username,password,email from users" //执行sql rows, err := utils.Db.Query(sqlStr) if err != nil { return nil, err } //定义一个User切片 var users []*User //遍历 for rows.Next() { var userID int var userename string var password string var email string //将各个字段的值读取到以上三个变量中 err := rows.Scan(&userID, &user.Username, &password, &email) if err != nil { return nil, err } //将三个变量的值赋给User结构体 u := &User{ ID: userID, Username: userename, Password: password, Email: email, } //将u添加到users切片中 users = append(users, u) } return users, nil }
model/test_user.go
package model import ( "fmt" "testing" ) //TestMain函数可以再测试是函数之前做一些其他的操作 func TestMain(m *testing.M) { fmt.Println("测试开始:") //通过m.Run()来执行测试函数 m.Run() } /* 如果一个测试函数的函数名的不是以 Test 开头,那么在使用 go test 命令时默 认不会执行,不过我们可以设置该函数时一个子测试函数,可以在其他测试函 数里通过 t.Run 方法来执行子测试函数,具体代码如下 */ func TestUser(t *testing.T) { fmt.Println("开始测试user中相关方法") //通过t.Run()来执行子测试函数 t.Run("测试添加用户:", testAddUser) t.Run("正在测试获取一个用户:", testGetUserID) } //子测试函数 //如果函数名不是以Test开头的那吗函数默认不执行,我们可以将它设置为一个子测试函数 func testAddUser(t *testing.T) { fmt.Println("子测试函数执行") user := &User{ Username: "admin5", Password: "123456", Email: "admin5@124.com", } //将user添加到数据库中 user.AddUser() } //子测试函数 //获取一条记录 func testGetUserID(t *testing.T) { u := &User{} user, _ := u.GetUserByID(1) fmt.Println("用户的信息是:", *user) } //在user_test.go中测试添加员工的方法 func TestAddUser(t *testing.T) { user := &User{ Username: "admin4", Password: "123", Email: "admins4@11.com", } //将user添加到数据库中 user.AddUser() } //获取所有数据
util/db.go
package utils import ( "database/sql" _"github.com/go-sql-driver/mysql" ) var ( Db *sql.DB err error ) func init() { Db, err = sql.Open("mysql", "root:root@tcp(localhost:3306)/test") if err != nil { panic(err.Error()) } }
请求 与响应
main.go
package main import ( "encoding/json" "fmt" "io/ioutil" "net/http" ) //创建处理器函数 func handler1(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "测试http协议") //获取内容长度 length := r.ContentLength //创建一个字节切片 body := make([]byte, length) //读取请求体 r.Body.Read(body) fmt.Fprintln(w, "请求体中的内容:", string(body)) } //创建处理器函数 func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "测试http协议") //解析表单 r.ParseForm() //获取请求参数 //在r.Form之前一定要调用rParseForm fmt.Fprintln(w, "请求参数:", r.Form) //请求参数: map[password:[67889] username:[admin]] } //PostForm,只获取表单中的参数 func handler3(w http.ResponseWriter, r *http.Request) { //解析表单 r.ParseForm() //获取请求参数 //如果enctype属性值为multipart/form-data //需要使用MultipartForm字段 fmt.Fprintln(w, "请求参数为:", r.PostForm) //请求参数为: map[password:[999] username:[jack]] } //直接获取请求参数 func handler4(w http.ResponseWriter, r *http.Request) { //获取请求参数 fmt.Fprintln(w, "请求参数username的值为。", r.FormValue("username")) //请求参数username的值为。 rose } //直接获取请求参数 func handler5(w http.ResponseWriter, r *http.Request) { //获取请求参数 fmt.Fprintln(w, "请求参数username的值为。", r.PostFormValue("username")) //请求参数username的值为。 rose } // r.FormValue //处理上传文件 func handler6(w http.ResponseWriter, r *http.Request) { //解析表单 r.ParseMultipartForm(1024) //打印表单数据 fmt.Fprintln(w, r.MultipartForm) //&{map[username:[kkk]] map[photo:[0xc000100000]]} } //打开上传文件,显示 func handler7(w http.ResponseWriter, r *http.Request) { //解析表单 r.ParseMultipartForm(1024) fileHeader := r.MultipartForm.File["photo"][0] file, err := fileHeader.Open() if err == nil { data, err := ioutil.ReadAll(file) if err == nil { fmt.Fprintln(w, string(data)) } } } //net/http 提供的 FormFile 方法可以快速的获取被上传的文件,但是只能处理上 //传一个文件的情况 func handler8(w http.ResponseWriter, r *http.Request) { file, _, err := r.FormFile("photo") if err == nil { data, err := ioutil.ReadAll(file) if err == nil { fmt.Fprintln(w, string(data)) } } } /* 响应部分 客户端响应 */ func handler9(w http.ResponseWriter, r *http.Request) { w.Write([]byte("你的请求我已经收到")) } //给客户端响应一个html页面 //处理器中的代码 func handler10(w http.ResponseWriter, r *http.Request) { html := ` <html> <head> <title>测试响应内容为网页</title> <meta charset="utf-8" /> </head> <body> 我是以网页的形式响应过来的! </body> </html> ` w.Write([]byte(html)) } //user结构体 type User struct { ID int Username string Password string } //给客户端响应json格式数据 func handler11(w http.ResponseWriter, r *http.Request) { //设置响应头中内容的类型 w.Header().Set("Content-Type", "application/json") user := User{ ID: 1, Username: "admin", Password: "123456", } //将user转换为json格式 json, _ := json.Marshal(user) w.Write(json) } //让客户端重定向 func handler12(w http.ResponseWriter, r *http.Request) { //一下操作必须要在WriteHeader之前执行 w.Header().Set("Location", "https://www.baidu.com") w.WriteHeader(302) } func main() { http.HandleFunc("/getBody", handler4) http.HandleFunc("/upload", handler8) //响应部分 http.HandleFunc("/res", handler12) //路由 http.ListenAndServe(":8080", nil) }
index.html
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <form action="http://localhost:8080/getBody?username=admin&pwd=123" method="post"> 用户名:<input type="text" name="username"/><br/> 密码:<input type="password" name="password"/><br/> <input type="submit"> </form> <br> <form action="http://localhost:8080/upload" method="post" enctype="multipart/form-data"> 用户名:<input type="text" name="username"/><br/> 文件:<input type="file" name="photo"/><br/> <input type="submit"> </form> </body> </html>
模板
package main import ( "html/template" "math/rand" "net/http" "time" ) func handler(w http.ResponseWriter, r *http.Request) { //解析模板文件 t := template.Must(template.ParseFiles("hello.html")) //声明一个变量 age := 16 //执行模板 t.Execute(w, age > 18) } //迭代动作 func handler1(w http.ResponseWriter, r *http.Request) { //解析模板文件 t := template.Must(template.ParseFiles("hello1.html")) //声明一个字符串切片 stars := []string{"jack", "roe", "baihe"} //执行模板 t.Execute(w, stars) } // func handler2(w http.ResponseWriter, r *http.Request) { //解析模板文件 t := template.Must(template.ParseFiles("hello2.html")) //执行模板 t.Execute(w, "狸猫") } //包含 // func handler3(w http.ResponseWriter, r *http.Request) { //解析模板文件 t := template.Must(template.ParseFiles("hello3.html", "hello3_ext.html")) //执行模板 t.Execute(w, "测试包含") } //同一个模板文件内定义 //定义动作 func handler4(w http.ResponseWriter, r *http.Request) { //解析模板文件 t := template.Must(template.ParseFiles("hello4.html")) //执行模板 t.ExecuteTemplate(w, "model", "") } //从其他文件包含 func handler5(w http.ResponseWriter, r *http.Request) { rand.Seed(time.Now().Unix()) var t *template.Template if rand.Intn(5) > 2 { //解析模板文件 t = template.Must(template.ParseFiles("hello5.html", "hello5_content1.html")) } else { //解析模板文件 t = template.Must(template.ParseFiles("hello5.html", "hello5_content2.html")) } //执行模板 t.ExecuteTemplate(w, "model", "") } //块动作 func handler6(w http.ResponseWriter, r *http.Request) { rand.Seed(time.Now().Unix()) var t *template.Template if rand.Intn(5) > 2 { //解析模板文件 t = template.Must(template.ParseFiles("hello6.html", "hello6_content1.html")) } else { //解析模板文件 t = template.Must(template.ParseFiles("hello6.html")) } //执行模板 t.ExecuteTemplate(w, "model", "") } func main() { http.HandleFunc("/t", handler) http.HandleFunc("/t1", handler1) http.HandleFunc("/t2", handler2) http.HandleFunc("/t3", handler3) http.HandleFunc("/t4", handler4) http.HandleFunc("/t5", handler5) http.HandleFunc("/t6", handler6) //路由 http.ListenAndServe(":8080", nil) }
cookie
package main import ( "fmt" "net/http" ) //cookie使用 func handler1(w http.ResponseWriter, r *http.Request) { cookie1 := http.Cookie{ Name: "user1", Value: "admin", HttpOnly: true, } cookie2 := http.Cookie{ Name: "user2", Value: "superAdmin", HttpOnly: true, } //将Cookie发送给浏览器,几天假第一个Cookie w.Header().Set("Set-Cookie", cookie1.String()) //再添加一个Cookie w.Header().Add("Set-Cookie", cookie2.String()) } //方式二设置cookie func handler2(w http.ResponseWriter, r *http.Request) { cookie1 := http.Cookie{ Name: "user1", Value: "admin", HttpOnly: true, } cookie2 := http.Cookie{ Name: "user2", Value: "admin2", HttpOnly: true, } //设置cookie http.SetCookie(w, &cookie1) http.SetCookie(w, &cookie2) } //读取cookie func handler3(w http.ResponseWriter, r *http.Request) { //获取请求头中的Cookie cookies := r.Header["Cookie"] fmt.Fprintln(w, cookies) } //设置失效时间 func handler4(w http.ResponseWriter, r *http.Request) { cookie := http.Cookie{ Name: "user", Value: "perisistAdmin", HttpOnly: true, MaxAge: 60, } //将cokkie发送给浏览器 w.Header().Set("Set-Cookie", cookie.String()) } func main() { http.HandleFunc("/c1", handler1) http.HandleFunc("/c2", handler2) http.HandleFunc("/c3", handler3) http.HandleFunc("/c4", handler4) //路由 http.ListenAndServe(":8080", nil) }
未完待续。。。