gin_restful的项目目录。
每个目录的意思描述:
对gin_restful项目进行mod处理:
# 1. 去到自己的gin_restful项目目录路径下。 cd xxx\gin_restful\ # 2. 如果之前以及mod init,可以删除这些文件。主要是go.mod、go.sum。 rm go.* # 3. 进行mod初始化。 # 注意:后面跟着的工程名gin_restful请设置成对应所在的根目录名字,否则在build时会报错。 go mod init gin_restful # 4. 构建,此时会自动帮你下载项目用到的第三方库。 go build
此时会看到程序运行起来。我们先把程序关掉。
api/users.go:
package api import ( "fmt" . "gin_restful/models" "net/http" "strconv" "github.com/gin-gonic/gin" ) //index func IndexUsers(c *gin.Context) { c.String(http.StatusOK, "It works") } //获得所有记录 func GetAll(c *gin.Context) { p := Person{} rs, _ := p.GetRows() c.JSON(http.StatusOK, gin.H{ "list": rs, }) } //增加一条记录 func AddUsers(c *gin.Context) { name := c.Request.FormValue("name") telephone := c.Request.FormValue("telephone") fmt.Println("name:", name) fmt.Println("telephone:", telephone) if name == "" { msg := fmt.Sprintf("name字段错误") c.JSON(http.StatusBadRequest, gin.H{ "msg": msg, }) return } person := Person{ Name: name, Telephone: telephone, } id := person.Create() msg := fmt.Sprintf("insert 成功 %d", id) c.JSON(http.StatusOK, gin.H{ "msg": msg, }) } //获得一条记录 func GetOne(c *gin.Context) { ids := c.Param("id") id, _ := strconv.Atoi(ids) p := Person{ Id: id, } rs, _ := p.GetRow() c.JSON(http.StatusOK, gin.H{ "result": rs, }) } func UpdateUser(c *gin.Context) { ids := c.Request.FormValue("id") id, _ := strconv.Atoi(ids) telephone := c.Request.FormValue("telephone") person := Person{ Id: id, Telephone: telephone, } row := person.Update() msg := fmt.Sprintf("updated successful %d", row) c.JSON(http.StatusOK, gin.H{ "msg": msg, }) } //删除一条记录 func DelUser(c *gin.Context) { ids := c.Request.FormValue("id") id, _ := strconv.Atoi(ids) row := Delete(id) msg := fmt.Sprintf("delete successful %d", row) c.JSON(http.StatusOK, gin.H{ "msg": msg, }) }
db/mysql.go:
package db import ( "database/sql" "fmt" "log" _ "github.com/go-sql-driver/mysql" ) // 全局的mysql线程池对象。 var SqlDB *sql.DB // 一个包里,名字为init的函数会自动被调用。并且在main开始前被调用。如不想被自动调用可以将名字改掉。 // 相当于C++的static静态变量、全局变量在编译时就被初始化了。 func init() { fmt.Println("sql init") // 包里的init自动调用,在main前执行。所以这句话会在main前面打印。 var err error SqlDB, err = sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/go_test?charset=utf8mb4") if err != nil { log.Fatal(err.Error()) } err = SqlDB.Ping() if err != nil { log.Fatal(err.Error()) } SqlDB.SetMaxIdleConns(20) SqlDB.SetMaxOpenConns(20) }
models/users.go:
package models import ( "gin_restful/db" "log" ) type Person struct { Id int `json:"id" form:"id"` Name string `json:"name" form:"name"` Telephone string `json:"telephone" form:"telephone"` } //插入 func (person *Person) Create() int64 { rs, err := db.SqlDB.Exec("INSERT into users (name, telephone) value (?,?)", person.Name, person.Telephone) if err != nil{ log.Fatal(err) } id, err := rs.LastInsertId() if err != nil{ log.Fatal(err) } return id } //查询一条记录 func (p *Person) GetRow() (person Person, err error) { person = Person{} err = db.SqlDB.QueryRow("select id,name,telephone from users where id = ?", p.Id).Scan(&person.Id, &person.Name, &person.Telephone) return } //查询所有记录 func (person *Person) GetRows() (persons []Person, err error) { rows, err := db.SqlDB.Query("select id,name,telephone from users") for rows.Next(){ person := Person{} err := rows.Scan(&person.Id, &person.Name, &person.Telephone) if err != nil { log.Fatal(err) } persons = append(persons, person) } rows.Close() return } //修改 func (person *Person) Update() int64{ rs, err := db.SqlDB.Exec("update users set telephone = ? where id = ?", person.Telephone, person.Id) if err != nil { log.Fatal(err) } rows, err := rs.RowsAffected() if err != nil { log.Fatal(err) } return rows } //删除一条记录 func Delete(id int) int64 { rs, err := db.SqlDB.Exec("delete from users where id = ?", id) if err != nil { log.Fatal() } rows, err := rs.RowsAffected() if err != nil { log.Fatal() } return rows }
router.go:
package main import ( . "gin_restful/api" "github.com/gin-gonic/gin" ) // 注册路由器。 func initRouter() *gin.Engine { router := gin.Default() router.GET("/", IndexUsers) // http://192.168.1.1:8806 // 2. 设置路由群组,路由群组可以设置多个。 // 例如设置用户组与部分组等等。 users := router.Group("api/v1/users") { users.GET("", GetAll) // http://192.168.1.1:8806/api/v1/users users.POST("/add", AddUsers) // http://192.168.1.1:8806/api/v1/users/add users.GET("/get/:id", GetOne) // http://192.168.1.1:8806/api/v1/users/get/5 users.POST("/update", UpdateUser) // http://192.168.1.1:8806/api/v1/users/update users.POST("/del", DelUser) // http://192.168.1.1:8806/api/v1/users/del } departments := router.Group("api/v1/departments") { departments.GET("", GetAll) // http://192.168.1.1:8806/api/v1/departments departments.POST("/add", AddUsers) // http://192.168.1.1:8806/api/v1/departments/add departments.GET("/get/:id", GetOne) // http://192.168.1.1:8806/api/v1/departments/get/5 departments.POST("/update", UpdateUser) // http://192.168.1.1:8806/api/v1/departments/update departments.POST("/del", DelUser) // http://192.168.1.1:8806/api/v1/departments/del } return router }
main.go:
package main import ( "fmt" "gin_restful/db" ) // go mod init xx_project // go build // ./xx_project func main() { fmt.Println("main start") // 1. 初始化mysql(自动调用init),并设置mysql的关闭函数。 if db.SqlDB != nil { defer db.SqlDB.Close() } // 2. http服务开启前,提前注册路由器参数。 fmt.Println("main 111") router := initRouter() fmt.Println("main 222") // 3. 依赖返回的router,启动http服务器。 // 启动后,如果客户端请求相关api,那么会调用相关的函数进行处理。 router.Run(":8806") fmt.Println("main 444") }
为了进行演示,我们重新额外创建一个user表。
执行go_test.sql文件:
CREATE DATABASE IF NOT EXISTS go_test; use go_test; CREATE TABLE `users` ( `id` BIGINT(20) NOT NULL AUTO_INCREMENT, `name` VARCHAR(20) DEFAULT '', `telephone` VARCHAR(11) DEFAULT '', PRIMARY KEY(`id`) )ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4;
演示结果:
1)http://127.0.0.1:8806/api/v1/users。
2)http://127.0.0.1:8806/api/v1/users/add。注意要求是POST请求,如果使用GET请求会返回404。说明Gin当请求的方法不符合时,会返回404。
3)http://127.0.0.1:8806/api/v1/users/get/1。
4)http://127.0.0.1:8806/api/v1/users/update。
5)http://127.0.0.1:8806/api/v1/users/del。