一.課程目標
- 本課程目標是讓新手能夠在最短的時間內瞭解到golang的增刪改查流程. 從而讓入門web開發更加容易.
- 本實例是快速實現一個用戶的增刪改查, 採用前後端分離模式, 後端採用
gorose orm
+gin框架
完成api的開發, 前端使用原生html+css+jquery+ajax
交互數據. - 本項目源碼已經發布到github: https://github.com/gohouse/go...
二.安裝基礎環境和依賴庫
# 安裝golang
yum -y install golang
# 安裝gin web框架
go get https://github.com/gin-gonic/gin
# 安裝gorose orm框架
go get https://github.com/gohouse/gorose
# 安裝sqlite3驅動
go get https://github.com/mattn/go-sqlite3
注: 這裏只是做一個centos下的命令行示例,實際使用中,建議使用vgo管理.
三.創建文件並開啓簡單的http服務
1.創建文件
cd $GOPATH/src/
mkdir gopro && cd gopro
touch main.go
2.編輯main.go
,內容如下
package main
import "github.com/gin-gonic/gin"
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.String(200, "歡迎來到golang入門用戶管理api服務系統")
})
// listen and serve on 0.0.0.0:8080 (for windows "localhost:8080" )
r.Run()
}
運行結果如下:
$ go run main.go
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] GET / --> main.BootGin.func1 (3 handlers)
[GIN-debug] GET /UserAdd --> main.UserAdd (4 handlers)
[GIN-debug] GET /UserList --> main.UserList (4 handlers)
[GIN-debug] GET /UserEdit --> main.UserEdit (4 handlers)
[GIN-debug] GET /UserDelete --> main.UserDelete (4 handlers)
[GIN-debug] Environment variable PORT is undefined. Using port :8080 by default
[GIN-debug] Listening and serving HTTP on :8080
瀏覽器訪問 http://localhost:8080 即可看到歡迎語了,一個基本的http服務已經搭建完畢
四.開發接口
初始化gorose orm
使用單例封裝一個gorose
初始驅動函數,這裏採用sqlite3
作爲示例的數據庫, 實際使用跟mysql
一致
var once sync.Once
var engin *gorose.Engin
//BootGorose 初始化gorose, 單例模式
func BootGorose() {
var err error
once.Do(func() {
engin, err = gorose.Open(&gorose.Config{
Driver: "sqlite3",
Dsn: "db2.sqlite",
})
if err != nil {
panic(err.Error())
}
})
}
封裝一個DB()
函數方便快捷調用
// DB orm快捷使用函數
func DB() gorose.IOrm {
return engin.NewOrm()
}
初始化用戶表
該表作爲示例的增刪改查對象
// UserInit 初始化用戶表
// 實際使用中,建議不要放到代碼中,避免每一次都會執行
func UserInit() {
dbSql := `CREATE TABLE IF NOT EXISTS "users" (
"uid" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
"username" TEXT NOT NULL default "",
"age" integer NOT NULL default 0
)`
affected_rows, err := DB().Execute(dbSql)
if err != nil {
panic(err.Error())
}
if affected_rows == 0 {
return
}
}
增加用戶
1.添加路由
...
router.GET("/UserAdd", UserAdd)
...
2.編寫UserAdd
方法
func UserAdd(c *gin.Context) {
username := c.Query("username")
age := c.DefaultQuery("age", "0")
var data = make(map[string]interface{})
if username == "" {
c.JSON(http.StatusOK, FailReturn("用戶名不能爲空"))
return
}
data["username"] = username
if age != "0" {
data["age"] = age
}
affected_rows, err := DB().Table("users").Data(data).Insert()
if err != nil {
c.JSON(http.StatusOK, FailReturn(err.Error()))
return
}
c.JSON(http.StatusOK, SuccessReturn(affected_rows))
}
這裏新增了兩個工具函數SuccessReturn()
和FailReturn()
,方便api統一返回使用,具體方法如下:
// SuccessReturn api正確返回函數
func SuccessReturn(msg interface{}) map[string]interface{} {
var res = make(map[string]interface{})
res["data"] = msg
res["code"] = http.StatusOK
res["msg"] = "success"
return res
}
// FailReturn api錯誤返回函數
func FailReturn(msg interface{}) map[string]interface{} {
var res = make(map[string]interface{})
res["data"] = ""
res["code"] = http.StatusBadRequest
res["msg"] = msg
return res
}
3.我們運行並測試一下效果,瀏覽器訪問: http://localhost:8080/UserAdd?username=fizz .
瀏覽器顯示如下內容, 則表示成功.
{
"code": 200,
"data": 1,
"msg": "success"
}
我們可以繼續執行,多添加幾條數據,方便測試:
http://localhost:8080/UserAdd?username=fizz2&age=18
等我們完善一下查看接口, 就可以查看剛纔添加的數據了
查看用戶
1.添加路由
...
router.GET("/UserList", UserList)
...
2.編寫UserList
方法
// UserList 獲取用戶列表
func UserList(c *gin.Context) {
// 默認查詢10條數據
userList, err := DB().Table("users").Limit(10).Get()
if err != nil {
c.JSON(http.StatusOK, FailReturn(err.Error()))
return
}
c.JSON(http.StatusOK, SuccessReturn(userList))
}
3.我們運行並測試一下效果,瀏覽器訪問: http://localhost:8080/UserList
瀏覽器顯示如下內容, 證明我們剛纔添加的數據是正確的
{
"code": 200,
"data": [
{
"age": 0,
"uid": 1,
"username": "fizz"
},
{
"age": 18,
"uid": 2,
"username": "fizz2"
}
],
"msg": "success"
}
修改用戶
1.添加路由
...
router.GET("/UserEdit", UserEdit)
...
2.編寫UserEdit
方法
// UserEdit 用戶編輯
func UserEdit(c *gin.Context) {
// 按照主鍵編輯
uid := c.Query("uid")
username := c.DefaultQuery("username", "")
age := c.DefaultQuery("age", "0")
if uid == "" {
c.JSON(http.StatusOK, FailReturn("用戶id不能爲空"))
return
}
if username == "" && age == "0" {
c.JSON(http.StatusOK, FailReturn("未修改"))
return
}
var data = make(map[string]interface{})
if username != "" {
data["username"] = username
}
if age != "0" {
data["age"] = age
}
// 執行入庫操作
affected_rows, err := DB().Table("users").Where("uid", uid).Data(data).Update()
if err != nil {
c.JSON(http.StatusOK, FailReturn(err.Error()))
return
}
c.JSON(http.StatusOK, SuccessReturn(affected_rows))
}
3.我們運行並測試一下效果,瀏覽器訪問: http://localhost:8080/UserEdit?username=fizz22&uid=2
瀏覽器顯示如下內容, 證明修改成功
{
"code": 200,
"data": [
{
"age": 0,
"uid": 1,
"username": "fizz"
},
{
"age": 18,
"uid": 2,
"username": "fizz22"
}
],
"msg": "success"
}
刪除用戶
1.添加路由
...
router.GET("/UserDelete", UserDelete)
...
2.編寫UserDelete
方法
// UserDelete 用戶刪除
func UserDelete(c *gin.Context) {
// 按主鍵刪除
uid := c.Query("uid")
if uid == "" {
c.JSON(http.StatusOK, FailReturn("用戶id不能爲空"))
return
}
affected_rows, err := DB().Table("users").Where("uid", uid).Delete()
if err != nil {
c.JSON(http.StatusOK, FailReturn(err.Error()))
return
}
c.JSON(http.StatusOK, SuccessReturn(affected_rows))
}
3.我們運行並測試一下效果,瀏覽器訪問: http://localhost:8080/UserDelete?uid=2
瀏覽器顯示如下內容, 證明刪除成功
{
"code": 200,
"data": 0,
"msg": "success"
}
4.最後我們再查看一下數據, http://localhost:8080/UserList
{
"code": 200,
"data": [
{
"age": 0,
"uid": 1,
"username": "fizz"
}
],
"msg": "success"
}
發現uid=2的數據已經刪掉了,到此, 增刪改查的api接口全部搞定
完成前端頁面
1. 編寫html+css
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>golang用戶管理示例</title>
<style>
#user-box{
max-width: 600px;
margin: 0 auto;
}
table{
text-align: center;
border: 1px solid #000;
}
th{
width: 150px;
}
</style>
</head>
<body>
<center><h1>歡迎來到golang入門用戶管理api服務系統</h1></center>
<hr>
<div id="user-box">
<button onclick="UserAdd()">新增</button>
<table>
<tr>
<th>uid</th>
<th>用戶名</th>
<th>年齡</th>
<th>操作</th>
</tr>
</table>
</div>
</body>
</html>
2. 編寫增加和修改的模態框彈層
<div id="modal">
<!-- 模態框 -->
<dialog>
<p>操作</p>
<hr>
<input type="hidden" id="uid">
<p>
用戶名: <br>
<input type="text" id="username">
</p>
<p>
年 齡: <br>
<input type="text" id="age">
</p>
<button onclick="UserSubmit()">提交</button>
<button onclick="dialog.hide()">關閉</button>
</dialog>
</div>
3. 編寫JavaScript
<script src="https://cdn.bootcss.com/jquery/3.4.1/jquery.min.js"></script>
<script>
var dialog = $("dialog");
var uid = $("#uid");
var username = $("#username");
var age = $("#age");
// 初始化數據
UserList();
function UserSubmit() {
var url = "http://localhost:8080/UserEdit";
var uidVal = uid.val();
if (uidVal=="") {
url = "http://localhost:8080/UserAdd"
}
$.get(url,{
uid:uid.val(),
username:username.val(),
age:age.val()
},function (e) {
console.log(e);
if (e.code!=200) {
alert("失敗")
}
// dialog.hide()
window.location.reload()
})
}
function UserAdd() {
dialogInit()
dialog.show()
}
function UserEdit(uidParam,usernameParam,ageParam) {
dialogInit()
dialog.show()
uid.val(uidParam)
username.val(usernameParam)
age.val(ageParam)
}
function UserDelete(uidParam) {
var url = "http://localhost:8080/UserDelete"
$.get(url,{uid,uidParam},function (e) {
console.log(e);
dialog.hide()
})
}
function dialogInit() {
uid.val("")
username.val("")
age.val("")
}
function UserList() {
var url = "http://localhost:8080/UserList"
$.get(url,{},function (e) {
if (e.code==200) {
if (e.data.length>0) {
for(var i in e.data) {
var data = e.data[i]
$("table").append("<tr>\n" +
" <td>"+data.uid+"</td>\n" +
" <td>"+data.username+"</td>\n" +
" <td>"+data.age+"</td>\n" +
" <td><a href='javascript:;' onclick='UserEdit("+data.uid+",\""+data.username+"\","+data.age+")'>編輯</a> | " +
"<a href='javascript:;' onclick='UserDelete("+data.uid+")'>刪除</a> </td>" +
" </tr>")
}
}
}
dialog.hide()
})
}
</script>
六.運行
訪問 index.html
即可, 效果如下, 原生html+css實現. 雖然醜了一點,但是麻雀雖小,五臟俱全,湊合着看下(^_^)