@Go Web
1)Web应用的工作原理
2)基本Go Web创建服务器代码编写
使用http.HandleFunc
方法
package main
import (
"net/http"
"fmt"
)
/*
创建一个net/http 服务,响应hello world demo
1. 创建一个函数用来,响应请求内容
2. 使用http.HandleFunc() 处理请求
3. 监听端口内容,等待用户端访问
*/
// 1. 创建一个函数用来,响应请求内容
func handler(w http.ResponseWriter, r *http.Request){
a := "hello world"
w.Write([]byte(a))
}
func main() {
fmt.Println("您已成功启动服务,Web请求监听localhost:8080端口")
// 2. 使用http.HandleFunc() 处理请求
http.HandleFunc("/",handler)
// 3. 监听端口内容,等待用户端访问
http.ListenAndServe("127.0.0.1:8080", nil)
}
使用http.Handle
方法,并且自定义一个MyHandler struct结构体满足handler这个接口.
package main
import (
"fmt"
"net/http"
)
/*
自己定义一个handler 处理请求
1. 创建一个结构体 myHenDler
2. 创建serverHttp(),并且给myHenDler 绑定指定方法serverHttp
3. main 中实例化结构体得到方法
4. 4. 使用Handle("/",&myHenDler),注意这里的myHenDler.ServerHttp 必须满足w http.ResponseWriter, r *http.Request
*/
//1. 创建一个结构体 myHenDler
type MyHandler struct {
}
//2. 创建serverHttp(),并且给myHenDler 绑定指定方法serverHttp
// 注意方法中w http.ResponseWriter, r *http.Request 为固定写法,不能随意修改
func (m *MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request){
a := "陈浩天编写的第一个后台web服务器"
w.Write([]byte(a))
}
func main() {
//3. main 中实例化结构体得到方法
myHenDler := MyHandler{}
fmt.Println("您已成功启动服务,Web请求监听localhost:8080端口")
//4. 使用Handle("/",&myHenDler),注意这里的myHenDler.ServerHttp 必须满足w http.ResponseWriter, r *http.Request
http.Handle("/",&myHenDler)
//5. 监听端口内容,等待用户端访问
http.ListenAndServe(":8080",nil)
}
使用自定义server结构体参数,详细配置ListenAndServe
,上述重复内容就没有过多赘述,了解即可
//4. 创建server结构
server := http.Server{
Addr: ":8080",
Handler: &myHenDler,
ReadTimeout: 2 * time.Second,
}
fmt.Println("您已成功启动服务,Web请求监听localhost:8080端口")
//4. 使用HandleFunc("/",myHenDler.ServeHTTP),注意这里的serverHttp 必须满足w http.ResponseWriter, r *http.Request
//http.Handle("/",&myHenDler)
//5. 使用server.ListenAndServe监听端口内容,等待用户端访问,因为server结构体中已经详细定义了,**所以使用ListenAndServe不用再传参数**
server.ListenAndServe()
使用自定义多路复用器
,上述重复内容就没有过多赘述
package main
import (
"fmt"
"net/http"
)
/*
自己定义一个ServeMux,通过新的ServeMux,处理http请求
1. 通过NewServeMux 创建一个新的多路复用器
2. 创建一个函数handler(w http.ResponseWriter, r *http.Request),固定格式
3. 监听端口,选择多路路由复用器mux
4. 调用mux的HandleFunc处理请求访问
*/
// 2. 创建一个函数handler(w http.ResponseWriter, r *http.Request),固定格式
func handler(w http.ResponseWriter, r *http.Request){
a := "自己创建多路复用器"
w.Write([]byte(a))
}
func main() {
// 1. 通过NewServeMux 创建一个新的多路复用器
mux := http.NewServeMux()
fmt.Println("您已成功启动服务,Web请求监听localhost:8080端口")
// 4. 调用mux的HandleFunc处理请求访问
mux.HandleFunc("/",handler)
// 3. 监听端口,选择多路复用器mux
http.ListenAndServe(":8082",mux)
}
@Go MySql
1)操作数据库前提
Go 语言中的database/sql 定义了对数据库的一系列操作。database/sql/driver包中定义了应被数据库驱动
实现的接口,我们需要导入第三方的数据库驱动,不过我们连接数据库之后对数据库操作大部分代码都是
通过sql包来实现的。
2)操作数据库编码
首先编写一个dbsql文件,获取数据库链接句柄。
package dbsql
import (
// 官方提供的接口文档,我们通过sql 包中的结构体函数
"database/sql"
"log"
// 我们只是要使用mysql 这个报下的init函数,所以前面用匿名导包方式,本文件并不会去调用mysql下的任何内容方法
_ "github.com/go-sql-driver/mysql"
)
/*
得到一个数据库句柄
1. 声明一个*sql.DB 类型的变量接受,sql.Open后的参数,err error 类型的变量判断句柄是否正常
2. 注意:这里的变量要大写,因为其他包中要使用到Db 和Err 这两个变量
** 本文件的作用:
用于获取到一个数据库句柄,将句柄返回给导入本包的文件使用
*/
var(
// 声明一个*sql.DB 类型的变量接受,sql.Open后的参数
Db *sql.DB
Err error
)
func init(){
Db, Err = sql.Open("mysql","root:a@199862@tcp(localhost:3306)/zhangsan")
if Err != nil {
log.Panicln("sql.Open is error:", Err)
}
}
得到数据库句柄后,操作数据库表users
insert 插入内容。
package users
import (
"log"
"goWeb/dbsql"
)
/*
创建结构体,对应数据库表中的字段,
为结构体绑定对应操作数据库表的方法
增删改查
//1. 创建User结构体
//2. 添加AddUser方法 (AddUser和AddUser2两种方法的区别在于一个使用了预处理,一个直接调用Exec 执行)
//3. 添加AddUser2方法
*/
// User 结构体 对应数据库表中的字段与类型
type User struct {
Id int
Username string
Password string
Email string
}
Adduser 预处理添加User的方法
func (user *User) AddUser() error {
/*
1. 编写SQL语句
2. 预处理
3. 执行
*/
// 写sql 语句
sqlStr := "insert into users (username,password,email) values(?,?,?)"
// 预处理
instmt, err := dbsql.Db.Prepare(sqlStr)
if err != nil {
log.Println("预处理异常")
return err
}
// 执行
_, err2 := instmt.Exec("admin","123456","admin@atguigu.com")
if err2 != nil {
log.Println("执行异常")
return err
}
return nil
}
Adduser2 添加User的方法
func (user *User) AddUser2() error {
/*
1. 编写SQL语句
2. 执行
*/
// 写sql 语句
sqlStr := "insert into users (username,password,email) values(?,?,?)"
// 执行语句
_, err := dbsql.Db.Exec(sqlStr,"admin2","666666","admin2@atguigu.com")
if err != nil {
log.Println("执行异常")
return err
}
return nil
}
SelectUsersAll 查询users表中所有方法
// Selectusers 查询users表所有方法
func (user *User) SelectUsersAll() ([]*User,error) {
/*
查询users表所有内容
1. 指定sql查询语句
2. 获取Rows结构体
3. 指定游标,通过游标一行一行读取数据,并且存储到一个结构体中
4. 创建一个Users []*User 切片
5. 将新的结构体存放到Users 这个切片当中
6. 返回Users 和err
*/
// 1. 指定sql查询语句
sqlStr := "select * from users"
// 4. 创建一个Users []*User 切片
var Users []*User
//2. 获取Rows结构体
rows, err := dbsql.Db.Query(sqlStr)
if err != nil {
fmt.Println("查询失败")
}
//3. 指定游标,每一次Next 指定下一行内容
for rows.Next(){
var id int
var username string
var password string
var email string
err := rows.Scan(&id, &username, &password, &email)
if err != nil {
break
}
var u *User = &User{
Id: id,
Username: username,
Password: password,
Email: email,
}
//5. 将新的结构体存放到Users 这个切片当中
Users = append(Users, u)
}
fmt.Println(Users)
//6. 返回Users 和err
return Users, err
}
Selectusers 查询users表一行方法,这里的问号是占位符
func (user *User) SelectUsersOne() (*User,error){
/*
Selectusers 查询users表一行方法
1. 指定sql查询语句
2. 获取Rows结构体
3. row.Scan 扫描该行内容所有字段,并一一对应赋值
4. 返回user结构体
*/
//1. 指定sql查询语句
sqlStr := "select * from users where id = ?"
//2. 获取Row结构体
row := dbsql.Db.QueryRow(sqlStr, user.Id)
//3. row.Scan 扫描该行内容所有字段,并一一对应赋值
err := row.Scan(&user.Id, &user.Username, &user.Password, &user.Email)
if err != nil {
return nil, err
}
//4. 返回user结构体
return user, nil
}
@GoWeb 处理请求
Go 语言的net/http 包提供了一系列用于表示HTTP报文的结构,我们可以使用它处理请求和发送响应,其中Request结构代表了客户端发送的请求报文,下面一起来学习操作一下。
获取请求路径r.URL.Path
,获取请求参数r.URL.RawQuery
// 自定义处理函数中,r.URL.Path 代表访问路径如(localhost/hello,那么本次显示的路径就是/hello),r.URL.RawQuery代表url?后面的参数如(localhost/hello?name=zhangsan&age=13),那么本次显示的内容就是name=zhangsan&age=13
func handler(w http.ResponseWriter, r *http.Request){
fmt.Printf("%v%v\n",
// 自定义处理函数中,r.URL.Path 代表访问路径如(localhost/hello,那么本次显示的路径就是/hello)
r.URL.Path,
//r.URL.RawQuery代表url?后面的参数如(localhost/hello?name=zhangsan&age=13),那么本次显示的内容就是name=zhangsan&age=13
r.URL.RawQuery)
}
读取请求头Header
中的信息
// 2. 创建一个处理请求函数handler(w http.ResponseWriter, r *http.Request),固定格式
func handler(w http.ResponseWriter, r *http.Request){
a = fmt.Sprintf("%v \n%v \n%v \n",
//r.Header 是一个map 类型,所有请求头信息以键值对方式存放在map中
r.Header,
//r.Header["Accept-Encoding"] 取头字段中的值以[] 切片形式返回
r.Header["Accept-Encoding"],
//r.Header["Accept-Encoding"] 取头字段中的值以值 形式返回
r.Header.Get("Accept-Encoding"))
w.Write([]byte(a))
}
读取请求体Body
中的信息
// 2. 创建一个处理请求函数handler(w http.ResponseWriter, r *http.Request),固定格式
func handler(w http.ResponseWriter, r *http.Request){
/*
读取Post请求发送过来的请求体内容,并返还给前端浏览器页面
r.ContentLength 获取请求体内容的长度
r.Body.Read 读取Body内容放到body[]byte切片中
w.Write(body) 将读取到的body返回给浏览器前端
*/
// 获取body长度
length := r.ContentLength
// 创建一个[]byteq
body := make([]byte, length)
// 读取请求体内容读取到body中
r.Body.Read(body)
// 将读取到的body返回给浏览器前端
w.Write(body)
}
获取请求参数
// r.Method 返回字符串返回当前客户端请求方法
if r.Method != "Get" {
// Post 请求
leng := r.ContentLength
body := make([]byte, leng)
r.Body.Read(body)
w.Write(body)
} else {
// Get 请求
r.ParseForm()
username := r.FormValue("username")
password := r.FormValue("password")
res := fmt.Sprintf("用户名:%v \n密码:%v",username,password)
w.Write([]byte(res))
}
@Goweb 响应客户端
1)向客户端返回字符串类型数据
// 按照固定类型返回
func handler(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
res := fmt.Sprintf("请求方法 %v\n请求用户名:%v\n请求用户密码: %v", r.Method, r.Form.Get("username"), r.Form.Get("password"))
// w.Write响应客户端内容
w.Write([]byte(res))
fmt.Println(r.URL.RawPath)
}
2)向客户端返回模板数据
func testTemplate(w http.ResponseWriter, r *http.Request) {
/*
前端响应,模板内容:
1. 解析模板,默认会选择第一个
2. 传入动态内容返回给前端
3. 若需要指定解析模板,t.ExecuteTemplate
*/
// 1. 解析模板,默认会选择第一个
t, _ := template.ParseFiles("index.html","hello.html")
// 2. 传入动态内容返回给前端
t.Execute(w, "hello world")
// 3. 若需要指定解析模板,t.ExecuteTemplate
t.ExecuteTemplate(w, "hello.html","hello 世界")
}
3)简单的首页登录,提交表单跳转首页
IndexHandler 登录页面
IndexHandler1 首页页面
编写以上两个函数,处理相关请求
登录提交表单数据,后台将数据拿出显示到主页面
package main
import (
"fmt"
"html/template"
"net/http"
)
/*
简单的首页登录,提交表单跳转首页
IndexHandler 登录页面
IndexHandler1 首页页面
编写以上两个函数,处理相关请求
登录提交表单数据,后台将数据拿出显示到主页面
*/
func IndexHandler(w http.ResponseWriter, r *http.Request){
// 解析模板
t, _ := template.ParseFiles("views/index.html")
// 返回模板内容
t.Execute(w,"")
}
func IndexHandler1(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
user := r.FormValue("username")
pwd := r.FormValue("password")
res := fmt.Sprintf("欢迎来到主页面 %v,\n您的密码是 %v",user,pwd)
w.Write([]byte(res))
}
func main() {
http.HandleFunc("/main", IndexHandler)
http.HandleFunc("/index", IndexHandler1)
fmt.Println("Web程序启动成功,请访问locahost地址80端口")
http.ListenAndServe(":80", nil)
}
4)http.StripPrefix路径重定向
func main() {
http.HandleFunc("/main", IndexHandler)
http.HandleFunc("/index", IndexHandler1)
//http.StripPrefix 类似于重定向,当客户端访问指定地址,触发函数http.FileServer打开重定向到指定路径,
//可以显示指定目录下内容,注意此处http.Dir只能指定目录,不能打开文件
http.Handle("/a/", http.StripPrefix("/a/",http.FileServer(http.Dir("views/static"))))
fmt.Println("Web程序启动成功,请访问locahost地址80端口")
http.ListenAndServe(":80", nil)
}