go post json 多维_Go操作MySql数据库的2种方式

14a21a9417e45d0d5905d50858b0ce66.gif

作者:徐超,原文:

https://xuchao918.github.io/2019/06/13/Go操作MySql数据库的方式/

Go操作Mysql数据库

使用Go操作MySQL等数据库,一般有两种方式:一是使用database/sql接口,直接在代码里硬编码sql语句;二是使用gorm,即对象关系映射的方式在代码里抽象的操作数据库。一般推荐使用第二种方式。

使用database/sql接口

Go没有内置的驱动支持任何数据库,但是Go定义了database/sql接口,用户可以基于驱动接口开发相应数据库的驱动。但缺点是,直接用 github.com/go-sql-driver/mysql 访问数据库都是直接写 sql,取出结果然后自己拼成对象,使用上面不是很方便,可读性也不好。

下载包

1
go get github.com/go-sql-driver/mysql

安装好 mysql 驱动之后,我们创建一张user表,并执行CRUD操作(增、删、改、查)。代码如下所示:

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
package mainimport (    "database/sql"    "fmt"    _ "github.com/go-sql-driver/mysql"    "time")//数据库连接信息const (	USERNAME = "root"	PASSWORD = "123456"	NETWORK = "tcp"	SERVER = "127.0.0.1"	PORT = 3306	DATABASE = "test")//user表结构体定义type User struct {	Id int `json:"id" form:"id"`	Username string `json:"username" form:"username"`	Password string `json:"password" form:"password"`	Status int   `json:"status" form:"status"`      // 0 正常状态, 1删除	Createtime int64 `json:"createtime" form:"createtime"`}func main() {	conn := fmt.Sprintf("%s:%s@%s(%s:%d)/%s",USERNAME, PASSWORD, NETWORK, SERVER, PORT, DATABASE)	DB, err := sql.Open("mysql", conn)	if err != nil {		fmt.Println("connection to mysql failed:", err)		return	}	    DB.SetConnMaxLifetime(100*time.Second)  //最大连接周期,超时的连接就close    DB.SetMaxOpenConns(100)                //设置最大连接数    CreateTable(DB)    InsertData(DB)    QueryOne(DB)    QueryMulti(DB)    UpdateData(DB)    DeleteData(DB)}func CreateTable(DB *sql.DB) {	sql := `CREATE TABLE IF NOT EXISTS users(	id INT(4) PRIMARY KEY AUTO_INCREMENT NOT NULL,	username VARCHAR(64),	password VARCHAR(64),	status INT(4),	createtime INT(10)	); `		if _, err := DB.Exec(sql); err != nil {        fmt.Println("create table failed:", err)        return    }	fmt.Println("create table successd")}//插入数据func InsertData(DB *sql.DB) {    result,err := DB.Exec("insert INTO users(username,password) values(?,?)","test","123456")    if err != nil{        fmt.Printf("Insert data failed,err:%v", err)        return    }    lastInsertID,err := result.LastInsertId()    //获取插入数据的自增ID    if err != nil {        fmt.Printf("Get insert id failed,err:%v", err)        return    }    fmt.Println("Insert data id:", lastInsertID)       rowsaffected,err := result.RowsAffected()  //通过RowsAffected获取受影响的行数    if err != nil {        fmt.Printf("Get RowsAffected failed,err:%v",err)        return    }    fmt.Println("Affected rows:", rowsaffected)}//查询单行func QueryOne(DB *sql.DB) {	user := new(User)   //用new()函数初始化一个结构体对象	row := DB.QueryRow("select id,username,password from users where id=?", 1)	//row.scan中的字段必须是按照数据库存入字段的顺序,否则报错	if err := row.Scan(&user.Id,&user.Username,&user.Password); err != nil {		fmt.Printf("scan failed, err:%v\n", err)		return	}	fmt.Println("Single row data:", *user)}//查询多行func QueryMulti(DB *sql.DB) {    user := new(User)    rows, err := DB.Query("select id,username,password from users where id = ?", 2)        defer func() {        if rows != nil {            rows.Close()   //关闭掉未scan的sql连接        }    }()    if err != nil {        fmt.Printf("Query failed,err:%v\n", err)        return    }    for rows.Next() {        err = rows.Scan(&user.Id, &user.Username, &user.Password)  //不scan会导致连接不释放        if err != nil {            fmt.Printf("Scan failed,err:%v\n", err)            return        }        fmt.Println("scan successd:", *user)    }}//更新数据func UpdateData(DB *sql.DB){    result,err := DB.Exec("UPDATE users set password=? where id=?","111111",1)    if err != nil{        fmt.Printf("Insert failed,err:%v\n", err)        return    }    fmt.Println("update data successd:", result)        rowsaffected,err := result.RowsAffected()    if err != nil {        fmt.Printf("Get RowsAffected failed,err:%v\n",err)        return    }    fmt.Println("Affected rows:", rowsaffected)}//删除数据func DeleteData(DB *sql.DB){    result,err := DB.Exec("delete from users where id=?",1)    if err != nil{        fmt.Printf("Insert failed,err:%v\n",err)        return    }    fmt.Println("delete data successd:", result)        rowsaffected,err := result.RowsAffected()    if err != nil {        fmt.Printf("Get RowsAffected failed,err:%v\n",err)        return    }    fmt.Println("Affected rows:", rowsaffected)}

执行程序,输出结果如下所示:

12345678
create table successdInsert data id: 1Affected rows: 1Single row data: {1 test 123456 0 0}update data successd: {0xc0000a0000 0xc000010280}Affected rows: 1delete data successd: {0xc0000a0000 0xc0000102b0}Affected rows: 1

OK,到这里大家是不是觉得这种实现方式很繁琐,假如要修改某个sql语句需要在代码中修改,这样很麻烦,代码设计也比较糟糕。因此这种方式并不推荐使用。

使用GORM

GORM(Object Relation Mapping),即Go语言中的对象关系映射,实际上就是对数据库的操作进行封装,对上层开发人员屏蔽数据操作的细节,开发人员看到的就是一个个对象,大大简化了开发工作,提高了生产效率。如GORM结合Gin等服务端框架使用可以开发出丰富的Rest API等。

首先,下载包

12
go get github.com/jinzhu/gormgo get github.com/gin-gonic/gin

使用Go的Gin框架和Gorm开发简单的CRUD API,代码如下

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
package mainimport (	"fmt"	"github.com/gin-gonic/gin"	"github.com/jinzhu/gorm"	_ "github.com/jinzhu/gorm/dialects/mysql"	"net/http")var MysqlDB *gorm.DBtype User struct {	Id   int    `gorm:"size:11;primary_key;AUTO_INCREMENT;not null" json:"id"`	Age  int    `gorm:"size:11;DEFAULT NULL" json:"age"`	Name string `gorm:"size:255;DEFAULT NULL" json:"name"`	//gorm后添加约束,json后为对应mysql里的字段}func main() {	MysqlDB, err := gorm.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/test?charset=utf8")	if err != nil {		fmt.Println("failed to connect database:", err)		return	}else{	    fmt.Println("connect database success")	    MysqlDB.SingularTable(true)	    MysqlDB.AutoMigrate(&User{}) //自动建表	    fmt.Println("create table success")	}	defer MysqlDB.Close()	Router()}func Router() {	router := gin.Default()	//路径映射	router.GET("/user", InitPage)	router.POST("/user/create", CreateUser)	router.GET("/user/list", ListUser)	router.PUT("/user/update", UpdateUser)	router.GET("/user/find", GetUser)	router.DELETE("/user/:id", DeleteUser)	router.Run(":8080")}//每个路由都对应一个具体的函数操作,从而实现了对user的增,删,改,查操作func InitPage(c *gin.Context) {	c.JSON(http.StatusOK, gin.H{		"message": "pong",	})}func CreateUser(c *gin.Context) {	var user User	c.BindJSON(&user)     //使用bindJSON填充对象	MysqlDB.Create(&user) //创建对象	c.JSON(http.StatusOK, &user)    //返回页面}func UpdateUser(c *gin.Context) {	var user User	id := c.PostForm("id")                //post方法取相应字段	err := MysqlDB.First(&user, id).Error //数据库查找主键=ID的第一行	if err != nil {		c.AbortWithStatus(404)		fmt.Println(err.Error())	} else {		c.BindJSON(&user)		MysqlDB.Save(&user) //提交更改		c.JSON(http.StatusOK, &user)	}}func ListUser(c *gin.Context) {	var user []User	line := c.Query("line")	MysqlDB.Limit(line).Find(&user) //限制查找前line行	c.JSON(http.StatusOK, &user)}func GetUser(c *gin.Context) {	id := c.Query("id")	var user User	err := MysqlDB.First(&user, id).Error	if err != nil {		c.AbortWithStatus(404)		fmt.Println(err.Error())	} else {		c.JSON(http.StatusOK, &user)	}}func DeleteUser(c *gin.Context)  {    id := c.Param("id")    var user User    MysqlDB.Where("id = ?", id).Delete(&user)    c.JSON(http.StatusOK, gin.H{        "data": "this has been deleted!",    })}

执行程序,输出结果如下所示:

12345678910
connect database successcreate table success......[GIN-debug] GET    /user                     --> main.InitPage (3 handlers)[GIN-debug] POST   /user/create              --> main.CreateUser (3 handlers)[GIN-debug] GET    /user/list                --> main.ListUser (3 handlers)[GIN-debug] PUT    /user/update              --> main.UpdateUser (3 handlers)[GIN-debug] GET    /user/find                --> main.GetUser (3 handlers)[GIN-debug] DELETE /user/:id                 --> main.DeleteUser (3 handlers)[GIN-debug] Listening and serving HTTP on :8080

如果要对上述接口进行测试,可以使用postman等工具.经测试可以实现对user的增,删,改,查操作。

如下,使用GET方法请求/user接口

9fef2d41e4e451430ad5d2e23a647723.png

小结

通过非常简短的代码,就可以实现功能强大的restful接口,go语言的优势也是非常明显的.关于gin和gorm还有更加深入的内容.掌握好这两个工具可以轻松的构建web应用。

6023a677c1d9c41257509a6162d2a443.gif

bddd357ac37c45549f43af2ec1a2eb7d.png

推荐阅读

  • 2019年已过半,精选往期 Kubernetes 干货文章

  • 最小成本落地微服务 DevOps 管道,CI/CD到 Kubernetes

  • KubeFed: Kubernetes Federation v2 详解

  • GitHub 发布CI/CD平台 Actions,支持Linux、MacOS、Win

  • Docker 技术鼻祖!

  • 强强对比 MongoDB与MySQL

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在 JavaWeb 中,发送 POST 请求有两常用方式:form 表单方式JSON 格式数据方式。 1. form 表单方式 发送 form 表单 POST 请求的步骤如下: 1)创建一个 URL 对象,指定要访问的服务器地址; 2)打开 URL 的连接; 3)设置连接的一些属性,如请求方法(POST)、是否使用缓存等; 4)设置请求头,指定请求的内容类型为 application/x-www-form-urlencoded; 5)获取连接的输出流,将请求参数写入流中; 6)读取服务器的响应,获取响应结果。 下面是一个示例代码: ```java URL url = new URL("http://example.com/api"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); // 设置请求头 conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded"); // 写入请求参数 String postData = "param1=value1&param2=value2"; OutputStream outputStream = conn.getOutputStream(); outputStream.write(postData.getBytes("UTF-8")); outputStream.flush(); // 读取响应结果 InputStream inputStream = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); String line; StringBuilder response = new StringBuilder(); while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); System.out.println(response.toString()); ``` 2. JSON 格式数据方式 发送 JSON 格式数据的 POST 请求的步骤如下: 1)创建一个 URL 对象,指定要访问的服务器地址; 2)打开 URL 的连接; 3)设置连接的一些属性,如请求方法(POST)、是否使用缓存等; 4)设置请求头,指定请求的内容类型为 application/json; 5)获取连接的输出流,将请求参数写入流中; 6)读取服务器的响应,获取响应结果。 下面是一个示例代码: ```java URL url = new URL("http://example.com/api"); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setDoOutput(true); // 设置请求头 conn.setRequestProperty("Content-Type", "application/json"); // 写入请求参数 String postData = "{\"param1\":\"value1\",\"param2\":\"value2\"}"; OutputStream outputStream = conn.getOutputStream(); outputStream.write(postData.getBytes("UTF-8")); outputStream.flush(); // 读取响应结果 InputStream inputStream = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream)); String line; StringBuilder response = new StringBuilder(); while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); System.out.println(response.toString()); ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值