http编程

) Go原生支持 http : import ("net/http")
) Go 的 http 服务性能和 nginx 比较接近
) 几行代码就可以实现一个 web 服务

http 服务端

// 示例代码:
package main import (
"fmt"
"net/http"
) func Hello(w http.ResponseWriter, r *http.Request){
fmt.Println("hello world\n")
fmt.Fprintf(w,"hello world") // 返回响应
} func main(){
http.HandleFunc("/",Hello) // 路由;第一个参数是路径,第二个参数是视图函数
err := http.ListenAndServe("0.0.0.0:8080",nil) // 监听并等待请求
if err != nil{
fmt.Println("http listened failed")
}
}

http 客户端

// 示例代码:
package main import (
"fmt"
"net/http"
"io/ioutil"
) func main(){
ret,err := http.Get("https://www.baidu.com/") // 向一个服务器发送 GET 请求;返回的数据都在 ret.Body 里面
if err != nil {
fmt.Println("get err:",err)
return
} data,err := ioutil.ReadAll(ret.Body) // 返回的数据都在 ret.Body 里面
if err != nil {
fmt.Println("get data err:",err)
return
} fmt.Printf("Type:%T\n",data)
fmt.Println(string(data))
} // 运行结果:
[root@NEO example01_http_client]# go run main/main.go
Type:[]uint8
<html>
<head>
<script>
location.replace(location.href.replace("https://","http://"));
</script>
</head>
<body>
<noscript><meta http-equiv="refresh" content="0;url=http://www.baidu.com/"></noscript>
</body>
</html>
[root@NEO example01_http_client]#

http常见请求方法

)Get请求
)Post请求
)Put请求
)Delete请求
)Head请求 -- > 只请求页面的头部

发送 HEAD 请求

// 示例代码:
package main import (
"fmt"
"net/http"
) var urls = []string{
"http://www.baidu.com",
"http://www.google.com",
"http://www.taobao.com",
} func main(){
for _,v := range urls{
resp,err := http.Head(v) // 发送 Head 请求
if err != nil {
fmt.Printf("head %s failed,err:%v\n",v,err)
continue
}
fmt.Printf("head success,status:%v\n",resp.Status) // resp.Status --> 状态码
}
} // 运行结果:
[root@NEO example01_http_head_request]# go run main/main.go
head success,status: OK
head http://www.google.com failed,err:Head http://www.google.com: dial tcp 75.126.2.43:80: connect: connection timed out
head success,status: OK
[root@NEO example01_http_head_request]# // 自定义超时时间
// 示例代码:
package main import (
"fmt"
"net/http"
"time"
"net"
) var urls = []string{
"http://www.baidu.com",
"http://www.google.com",
"http://www.taobao.com",
} func main(){
for _,v := range urls{
c := http.Client{ // 自定义客户端
Transport: &http.Transport{
Dial: func(network, addr string) (net.Conn, error){
timeout := time.Second * // 自定义超时时间
return net.DialTimeout(network, addr, timeout)
},
},
} start := time.Now()
resp,err := c.Head(v) // 用自定义的客户端发送请求
end := time.Now()
interval := end.Sub(start)
fmt.Println("interval:",interval)
//resp,err := http.Head(v) // 发送 Head 请求
if err != nil {
fmt.Printf("head %s failed,err:%v\n",v,err)
continue
}
fmt.Printf("head success,status:%v\n",resp.Status) // resp.Status --> 状态码
}
} // 运行结果:
[root@NEO example01_http_head_request]# go run main/main.go
interval: .062376ms
head success,status: OK
interval: .000789206s
head http://www.google.com failed,err:Head http://www.google.com: dial tcp 69.63.184.142:80: i/o timeout
interval: .542763ms
head success,status: OK
[root@NEO example01_http_head_request]#

http 常见状态码:

http.StatusContinue =
http.StatusOK =
http.StatusFound =
http.StatusBadRequest =
http.StatusUnauthorized =
http.StatusForbidden =
http.StatusNotFound =
http.StatusInternalServerError =

表单处理:

// 示例代码:
package main
import (
"io"
"net/http"
) // 常量 form 是一段 html 代码
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></html></body>` func SimpleServer(w http.ResponseWriter, request *http.Request) { // 请求信息都在 request 中
io.WriteString(w, "<h1>hello, world</h1>") // 返回给客户端一段html代码
} func FormServer(w http.ResponseWriter, request *http.Request) {
w.Header().Set("Content-Type", "text/html") // w.Head().Set(key,val) ---> 设置响应头
switch request.Method { // request.Method --> 请求方法
case "GET":
io.WriteString(w, form) // 把 form 表单返回给客户端
case "POST":
request.ParseForm() // 需要先解析表单
io.WriteString(w, request.Form["in"][]) // request.Form["in"] 是一个数组
io.WriteString(w, "\n")
io.WriteString(w, request.FormValue("in")) // request.FormValue("in") ---> 获取表单中的值(name重复时,取最近的一个);推荐使用这个
}
}
func main() {
http.HandleFunc("/test1", SimpleServer)
http.HandleFunc("/test2", FormServer)
if err := http.ListenAndServe(":8088", nil); err != nil {
}
}

模板操作

1) 替换

main.go 文件内容如下:

// 示例代码:
package main import (
"fmt"
"os"
"text/template" // 导入 模板 包
) type Person struct {
Name string
age string
} func main() {
t, err := template.ParseFiles("./index.html") // 解析模板文件; t 是模板对象
if err != nil {
fmt.Println("parse file err:", err)
return
}
p := Person{Name: "Mary", age: ""} // 结构体对象首字母大写的字段可以导入到模板中
if err := t.Execute(os.Stdout, p); err != nil { // t.Execute() --> 执行模板对象,第一个参数表示输出到终端,第二个参数表示 导入的结构体对象
fmt.Println("There was an error:", err.Error())
}
}

index.html 代码如下:

<html>
<head>
// 结构体对象没有的字段不能导入,要不然会报错,如下
</head>
<body>
<p>{{.}} </p> // .表示 p 那个对象
<p> hello, {{.Name}}</p> // .Name 表示 p 对象 的Name字段的值 #}
// 首字母小写的字段也不能在模板中渲染
</body>
</html>

运行结果:

// 运行结果:
[root@NEO main]# go run main.go
<html>
<head>
// 结构体对象没有的字段不能导入,要不然会报错,如下
</head>
<body>
<p>{Mary } </p> // .表示 p 那个对象
<p> hello, Mary</p> // .Name 表示 p 对象 的Name字段的值 #}
// 首字母小写的字段也不能在模板中渲染
</body>
</html>
[root@NEO main]#

2) if 判断

main.go 文件内容:

// 示例代码:
package main import (
"fmt"
"text/template" // 导入 模板 包
"net/http"
) type Person struct {
Name string
Age int
} func RenderTemplate(w http.ResponseWriter, request *http.Request){
t, err := template.ParseFiles("./index.html") // 解析模板文件; t 是模板对象
if err != nil {
fmt.Println("parse file err:", err)
return
}
p := Person{Name: "Mary", Age: } // 结构体对象首字母大写的字段可以导入到模板中
if err := t.Execute(w, p); err != nil { // 模板写入到在 http.ResponseWriter 中,返回给客户端
fmt.Println("There was an error:", err.Error())
}
} func main() {
http.HandleFunc("/template",RenderTemplate)
if err := http.ListenAndServe(":8080",nil); err != nil {
}
}

index.html 文件内容:

<html>
<head>
</head>
<body>
/*
if 语法:
{{if ...}}
{{else}}
{{end}}
*/
{# gt 表示大于 #}
{{if gt .Age 18}}
<p>hello oldman,{{.Name}} </p>
{{else}}
<p>hello young {{.Name}}</p>
{{end}}
</body>
</html>

if常见操作符:

not 非
{{if not .condition}} 
{{end}} and 与
{{if and .condition1 .condition2}} 
{{end}} or 或
{{if or .condition1 .condition2}} 
{{end}} eq 等于
{{if eq .var1 .var2}} 
{{end}} ne 不等于
{{if ne .var1 .var2}} 
{{end}} lt 小于 (less than)
{{if lt .var1 .var2}} 
{{end}} le 小于等于
{{if le .var1 .var2}} 
{{end}} gt 大于
{{if gt .var1 .var2}} 
{{end}} ge 大于等于
{{if ge .var1 .var2}} 
{{end}}

模板中with的用法:

{{with .Var}}
{end}}

示例代码:

<html>
<head>
</head>
<body>
{{with .Name}} <!-- 通过这行的 with ,. 就代表 Name ;只有 with 语句中 . 是 Name -->
<p>hello, old man, {{.}}</p>
{{end}}
</body>
</html>

模板的循环:

{{range.}} 

{{end }}

示例代码:

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

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

安装连接数据库的第三方包:

go get -u github.com/go-sql-driver/mysql        // 安装 mysql 驱动
go get github.com/jmoiron/sqlx

链接mysql:

// 先在 数据库主机上分配权限,如下:
mysql> grant all privileges on gotest.* to 'root'@'172.16.1.%' identified by '';
mysql> flush privileges;
// 代码运行服务器内网地址: 172.16.1.122 database, err := sqlx.Open("mysql", "root:123456@tcp(172.16.1.51:3306)/gotest")
// 参数说明:
// "mysql" ---> 数据库类型
// root ---> 用户名
// 123456 ---> 密码
// tcp ---> 连接协议
// 172.16.1.50 ---> 数据库主机地址
// 3306 ---> 端口
// gotest ---> 数据库名称

go 数据库的增删改查

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" // sqlx 在 mysql 驱动的层面上又做了封装,会更好用些
) type Person struct {
UserId int `db:"user_id"` // tag 就是数据库中的列名
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 // Db 就代表一个数据库;Db 这个变量是线程安全的,因为其内部已经内置实现了一个 连接池 func init() { // init() 函数在 main 函数之前自动执行
database, err := sqlx.Open("mysql", "root:123456@tcp(172.16.1.51:3306)/gotest") // database 是一个数据库实例
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() // 刚插入的那条记录的 id
if err != nil {
fmt.Println("exec failed, ", err)
return
} fmt.Println("insert succ:", id)
}

Select 操作

err := Db.Select(&person, "select user_id, username, sex, email from person where user_id=?", )

示例代码:

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:123456@tcp(172.16.1.51:3306)/gotest")
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=?", ) // 从数据库中查询出来结果会自动填充到 person 这个结构体中
if err != nil {
fmt.Println("exec failed, ", err)
return
} fmt.Println("select succ:", person)
} // 运行结果:
[root@NEO example02_mysql_select]# go run main/main.go
select succ: [{ stu001 man stu01@qq.com}]
[root@NEO example02_mysql_select]#

update操作

_, err := Db.Exec("update person set username=? where user_id=?", "stu0001", )

示例代码:

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:123456@tcp(172.16.1.51:3306)/gotest")
if err != nil {
fmt.Println("open mysql failed,", err)
return
} Db = database
} func main() { _, err := Db.Exec("update person set username=? where user_id=?", "stu0001", ) // 更新操作
if err != nil {
fmt.Println("exec failed, ", err)
return
} }

Delete 操作

_, err := Db.Exec("delete from person where user_id=?", )

示例代码:

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:123456@tcp(172.16.1.51:3306)/gotest")
if err != nil {
fmt.Println("open mysql failed,", err)
return
} Db = database
} func main() { _, err := Db.Exec("delete from person where user_id=?", )
if err != nil {
fmt.Println("exec failed, ", err)
return
} fmt.Println("delete succ")
}

golang(10):web开发 & 连接数据库的更多相关文章

  1. Go语言学习之10 Web开发与Mysql数据库

    本节主要内容: 1. http编程2. mysql使用 1. http编程 (1)http编程分析 Go原生支持http,import(“net/http”) Go的http服务性能和nginx比较接 ...

  2. Golang Web开发时前端出现谜之空白换行的坑

    在使用Golang做Web开发时,有时候渲染出来的模板在前台显示时会出现一些奇怪的空白换行,具体特征就是查看css样式表并没有相关定义的空白部分. 分析: 查看出现问题页面的网页源代码,复制空白换行部 ...

  3. 基于gin的golang web开发:访问mysql数据库

    web开发基本都离不开访问数据库,在Gin中使用mysql数据库需要依赖mysql的驱动.直接使用驱动提供的API就要写很多样板代码.你可以找到很多扩展包这里介绍的是jmoiron/sqlx.另外还有 ...

  4. 基于gin的golang web开发:使用数据库事务

    在前文介绍访问数据库时介绍了github.com/jmoiron/sqlx包,本文基于这个包使用数据库事务. defer 在使用数据库事务之前,首先需要了解go语言的defer关键字.defer是go ...

  5. 基于gin的golang web开发:mysql增删改查

    Go语言访问mysql数据库需要用到标准库database/sql和mysql的驱动.标准库的Api使用比较繁琐这里再引入另一个库github.com/jmoiron/sqlx. go get git ...

  6. 基于gin的golang web开发:Gin技术拾遗

    本文是对前几篇文章的一些补充,主要包含两部分:单元测试和实际项目中使用路由的小问题. 拾遗1:单元测试 Golang单元测试要求代码文件以_test结尾,单元测试方法以Test开头,参数为*testi ...

  7. 基于gin的golang web开发:服务间调用

    微服务开发中服务间调用的主流方式有两种HTTP.RPC,HTTP相对来说比较简单.本文将使用 Resty 包来实现基于HTTP的微服务调用. Resty简介 Resty 是一个简单的HTTP和REST ...

  8. Golang+Protobuf+PixieJS 开发 Web 多人在线射击游戏(原创翻译)

    简介 Superstellar 是一款开源的多人 Web 太空游戏,非常适合入门 Golang 游戏服务器开发. 规则很简单:摧毁移动的物体,不要被其他玩家和小行星杀死.你拥有两种资源 - 生命值(h ...

  9. Web 开发中很实用的10个效果【附源码下载】

    在工作中,我们可能会用到各种交互效果.而这些效果在平常翻看文章的时候碰到很多,但是一时半会又想不起来在哪,所以养成知识整理的习惯是很有必要的.这篇文章给大家推荐10个在 Web 开发中很有用的效果,记 ...

随机推荐

  1. 树状数组优化dp,一维排序,一维离散化

    #include<iostream> #include<cstdio> #include<algorithm> #include<vector> #in ...

  2. python pip 使用

    一.修改 pip 源 Windows 在用户目录下新建 pip\pip.ini 文件,如:C:\Users\Administrator\pip\pip.ini [global] index-url = ...

  3. P3378 【模板】堆 (内含左偏树实现)

    P3378 [模板]堆 题解 其实就是一个小根堆啦,STL就可以解决,但是拥有闲情雅致的我学习了Jelly_Goat的左偏树,增加了代码长度,妙啊 Solution 1 STL STL 里面prior ...

  4. 异常值检验实战1--风控贷款年龄变量(附python代码)

    python风控评分卡建模和风控常识(博客主亲自录制视频教程) https://study.163.com/course/introduction.htm?courseId=1005214003&am ...

  5. springboot 静态资源访问,和文件上传 ,以及路径问题

    springboot 静态资源访问: 这是springboot 默认的静态资源访问路径  访问顺序依次从前到后(http://localhost:8080/bb.jpg) spring.resourc ...

  6. [go]gorhill/cronexpr用go实现crontab

    // crontab基础 // linux crontab // 秒粒度, 年配置(2018-2099) // 哪一分钟(0-59),哪小时(0-23),哪天(1-31),哪月(1-12),星期几(0 ...

  7. 一百零五:CMS系统之flask-mail使用和邮箱配置、发送邮件功能

    安装:pip install flask-mail 官方文档:https://pythonhosted.org/Flask-Mail/ 邮箱配置 MAIL_SERVER = 'smtp.qq.com' ...

  8. 数据分析电子商务B2C全流程_数据分析师

    数据分析电子商务B2C全流程_数据分析师 目前,绝大多数B2C的转化率都在1%以下,做的最好的也只能到3.5%左右(比如以卖图书为主的当当) 我想,所有的B2C都会关心三个问题:究竟那97%去了哪里? ...

  9. 转载:深入浅出 Java 8 Lambda 表达式

    原文地址:http://viralpatel.net/blogs/Lambda-expressions-java-tutorial/ OneAPM for Java 能够深入到所有 Java 应用内部 ...

  10. Python 面向对象(下)

    本篇博客承接自Python 面向对象(上) 四. 继承,实现,依赖,关联,聚合,组合 Python面向对象--继承,实现,依赖,关联,聚合,组合 五. 特殊成员 Python面向对象--类的特殊成员 ...