我們已經了解了Golang的Gin框架。對於Webservice服務,restful風格幾乎一統天下。Gin也天然的支持restful。下面就使用gin寫一個簡單的服務,麻雀雖小,五臟俱全。我們先以一個單文件開始,然后再逐步分解模塊成包,組織代碼。
Hello World
使用Gin的前提是安裝,我們需要安裝gin和mysql的驅動,具體的安裝方式就不在贅述。
創建一個文件夾用來為項目,新建一個文件main.go:
☁ newland tree
.
└── main.go
main.go
package main import ( "gopkg.in/gin-gonic/gin.v1" "net/http" ) func main() { router := gin.Default() router.GET("/", func(c *gin.Context) { c.String(http.StatusOK, "Hello world") }) router.Run(":8801") }
編譯運行
數據庫
安裝完畢框架,完成一次請求響應之后。接下來就是安裝數據庫驅動和初始化數據相關的操作了。首先,我們需要新建數據表。一個及其簡單的數據表:
CREATE TABLE `users` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(64) DEFAULT NULL, `telephone` varchar(12) DEFAULT '', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=13 DEFAULT CHARSET=utf8mb4;
創建數據表之后,初始化數據庫連接池:
db, err := sql.Open("mysql", "root:@tcp(127.0.0.1:3306)/test?parseTime=true") if err != nil{ log.Fatalln(err) } defer db.Close() db.SetMaxIdleConns(20) db.SetMaxOpenConns(20) if err := db.Ping(); err != nil{ log.Fatalln(err) }
db.Ping
的操作。
db.SetMaxIdleConns(20)
和
db.SetMaxOpenConns(20)
分別設置數據庫的空閑連接和最大打開連接,即向Mysql服務端發出的所有連接的最大數目。
CURD 增刪改查
Restful的基本就是對資源的curd操作。下面開啟我們的第一個api接口,增加一個資源。
增
var db *sql.DB
type Person struct {
Id int `json:"id" form:"id"`
Name string `json:"name" form:"name"`
Telephone string `json:"telephone" form:"telephone"`
}
func main() { ... //增加一條記錄 router.POST("/add", func(c *gin.Context) { name := c.Request.FormValue("name") telephone := c.Request.FormValue("telephone") person := Person{ Name:name, Telephone:telephone, } id := person.Create() msg := fmt.Sprintf("insert successful %d", id) c.JSON(http.StatusOK, gin.H{ "msg": msg, }) }) ... } //插入 func (person *Person) Create() int64 { rs, err := db.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 checkErr(err error) { if err != nil{ panic(err) } }
執行非query操作,使用db的Exec方法,在mysql中使用?
做占位符。最后我們把插入后的id返回給客戶端。請求得到的結果如下:
查
查詢列表 Query
上面我們增加了一條記錄,下面就獲取這個記錄,查一般有兩個操作,一個是查詢列表,其次就是查詢具體的某一條記錄。兩種大同小異。
為了給查詢結果綁定到golang的變量或對象,我們需要先定義一個結構來綁定對象。
router.GET("/users", func(c *gin.Context) { rs, _ := getRows() c.JSON(http.StatusOK, gin.H{ "list": rs, }) }) //查詢所有記錄 func getRows() (persons []Person, err error) { rows, err := db.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 }
返回結果如下:
查詢單條記錄 QueryRow
查詢列表需要使用迭代rows對象,查詢單個記錄,就沒這么麻煩了。雖然也可以迭代一條記錄的結果集。因為查詢單個記錄的操作實在太常用了,因此golang的database/sql也專門提供了查詢方法
router.GET("/users/:id", func(c *gin.Context) { id_string := c.Param("id") id, _ := strconv.Atoi(id_string) rs, _ := getRow(id) c.JSON(http.StatusOK, gin.H{ "result": rs, }) }) //查詢一條記錄 func getRow(id int) (person Person, err error) { person = Person{} err = db.QueryRow("select id,name,telephone from users where id = ?", id).Scan(&person.Id, &person.Name, &person.Telephone) return }
返回結果如下:
改
增刪改查,下面進行更新的操作。
router.POST("/users/update", func(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 (person *Person) Update() int64{ rs, err := db.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 }
返回結果如下:
刪
最后一個操作就是刪除了,刪除所需要的功能特性,上面的例子都覆蓋了。實現刪除也就特別簡單了:
//刪除一條記錄 router.POST("/users/del", func(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, }) }) func Delete(id int) int64 { rs, err := db.Exec("delete from users where id = ?", id) if err != nil { log.Fatal() } rows, err := rs.RowsAffected() if err != nil { log.Fatal() } return rows }
返回結果:
至此,基本的CURD操作的restful風格的API已經完成。內容其實不復雜,甚至相當簡單。