这是一个使用Go语言结合Vue.js的简单Todos项目,可以用来学习Go与Vue.js。
使用条件:
1.使用了Echo框架. Echo是类似Slim PHP 或 Lumen.的Go微框架,通过路由处理HTTP请求。
2.使用SQLite 数据库。
开发步骤:
1. 下载echo和SQLite:
$ go get github.com/labstack/echo
$ go get github.com/mattn/go-sqlite3
2.创建项目目录:
$ cd $GOPATH/src
$ mkdir go-echo-vue && cd go-echo-vue
3.创建todo.go文件:
// todo.go package main
import ( "github.com/labstack/echo" "github.com/labstack/echo/engine/standard" )
|
创建main函数:
// todo.go func main() { }
|
为了让VueJS能够和后端通讯,创建基本路由,首先创建Echo新实例,使用内建函数定义简单路由规则。
在main函数中写入这些规则:
// todo.go func main() { // Create a new instance of Echo e := echo.New()
e.GET("/tasks", func(c echo.Context) error { return c.JSON(200, "GET Tasks") }) e.PUT("/tasks", func(c echo.Context) error { return c.JSON(200, "PUT Tasks") }) e.DELETE("/tasks/:id", func(c echo.Context) error { return c.JSON(200, "DELETE Task "+c.Param("id")) })
// Start as a web server e.Run(standard.New(":8000")) }
|
启动:
$ go build todo.go
$ ./todo
为了测试路由,使用Chrome插件Postman.打开Postman,指向localhost:8000,使用各种HTTP动词测试/tasks
下面是初始化数据库,指定文件名为storage.db:
// todo.go package main import ( "database/sql"
"github.com/labstack/echo" "github.com/labstack/echo/engine/standard" _ "github.com/mattn/go-sqlite3" )
|
在main函数加入:
// todo.go func main() {
db := initDB("storage.db") migrate(db)
|
定义创建数据库和迁移数据表,initDB是打开db文件,如果不存在创建它。migrate是运行SQL创建Todo数据表。
// todo.go func initDB(filepath string) *sql.DB { db, err := sql.Open("sqlite3", filepath)
// Here we check for any db errors then exit if err != nil { panic(err) }
// If we don't get any errors but somehow still don't get a db connection // we exit as well if db == nil { panic("db nil") } return db }
func migrate(db *sql.DB) { sql := ` CREATE TABLE IF NOT EXISTS tasks( id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, name VARCHAR NOT NULL ); `
_, err := db.Exec(sql) // Exit if something goes wrong with our SQL statement above if err != nil { panic(err) } }
|
再次启动:
$ go build todo.go
$ ./todo
应该看到数据库文件存在目录,使用SQLite管理命令行进入可查看到数据库。
最后我们创建处理器Handler和Model,将路由接受和数据库连接起来。
Handler部分:
导入库:
package main import ( "database/sql" "go-echo-vue/handlers"
"github.com/labstack/echo" "github.com/labstack/echo/engine/standard" _ "github.com/mattn/go-sqlite3" )
|
用将创建的新handler设置路由:
// todo.go e := echo.New()
e.File("/", "public/index.html") e.GET("/tasks", handlers.GetTasks(db)) e.PUT("/tasks", handlers.PutTask(db)) e.DELETE("/tasks/:id", handlers.DeleteTask(db))
e.Run(standard.New(":8000")) }
|
Handler代码:
// handlers/tasks.go package handlers
import ( "database/sql" "net/http" "strconv"
"github.com/labstack/echo" )
// handlers/tasks.go
// GetTasks endpoint func GetTasks(db *sql.DB) echo.HandlerFunc { return func(c echo.Context) error { return c.JSON(http.StatusOK, "tasks") } }
// PutTask endpoint func PutTask(db *sql.DB) echo.HandlerFunc { return func(c echo.Context) error { return c.JSON(http.StatusCreated, H{ "created": 123, } }
// DeleteTask endpoint func DeleteTask(db *sql.DB) echo.HandlerFunc { return func(c echo.Context) error { id, _ := strconv.Atoi(c.Param("id")) return c.JSON(http.StatusOK, H{ "deleted": id, }) } }
|
Model部分代码,包括业务模型和数据库CRUD:
// models/tasks.go package models
import ( "database/sql"
_ "github.com/mattn/go-sqlite3" ) // models/tasks.go
// Task is a struct containing Task data type Task struct { ID int `json:"id"` Name string `json:"name"` }
// TaskCollection is collection of Tasks type TaskCollection struct { Tasks []Task `json:"items"` }
func GetTasks(db *sql.DB) TaskCollection { sql := "SELECT * FROM tasks" rows, err := db.Query(sql) // Exit if the SQL doesn't work for some reason if err != nil { panic(err) } // make sure to cleanup when the program exits defer rows.Close()
result := TaskCollection{} for rows.Next() { task := Task{} err2 := rows.Scan(&task.ID, &task.Name) // Exit if we get an error if err2 != nil { panic(err2) } result.Tasks = append(result.Tasks, task) } return result }
func PutTask(db *sql.DB, name string) (int64, error) { sql := "INSERT INTO tasks(name) VALUES(?)"
// Create a prepared SQL statement stmt, err := db.Prepare(sql) // Exit if we get an error if err != nil { panic(err) } // Make sure to cleanup after the program exits defer stmt.Close()
// Replace the '?' in our prepared statement with 'name' result, err2 := stmt.Exec(name) // Exit if we get an error if err2 != nil { panic(err2) }
return result.LastInsertId() }
func DeleteTask(db *sql.DB, id int) (int64, error) { sql := "DELETE FROM tasks WHERE id = ?"
// Create a prepared SQL statement stmt, err := db.Prepare(sql) // Exit if we get an error if err != nil { panic(err) }
// Replace the '?' in our prepared statement with 'id' result, err2 := stmt.Exec(id) // Exit if we get an error if err2 != nil { panic(err2) }
return result.RowsAffected() }
|
将Model插入Handler代码:
// handlers/tasks.go package handlers
import ( "database/sql" "net/http" "strconv"
"go-echo-vue/models"
"github.com/labstack/echo" )
// handlers/tasks.go
// GetTasks endpoint func GetTasks(db *sql.DB) echo.HandlerFunc { return func(c echo.Context) error { // Fetch tasks using our new model return c.JSON(http.StatusOK, models.GetTasks(db)) } }
// PutTask endpoint func PutTask(db *sql.DB) echo.HandlerFunc { return func(c echo.Context) error { // Instantiate a new task var task models.Task // Map imcoming JSON body to the new Task c.Bind(&task) // Add a task using our new model id, err := models.PutTask(db, task.Name) // Return a JSON response if successful if err == nil { return c.JSON(http.StatusCreated, H{ "created": id, }) // Handle any errors } else { return err } } }
// DeleteTask endpoint func DeleteTask(db *sql.DB) echo.HandlerFunc { return func(c echo.Context) error { id, _ := strconv.Atoi(c.Param("id")) // Use our new model to delete a task _, err := models.DeleteTask(db, id) // Return a JSON response on success if err == nil { return c.JSON(http.StatusOK, H{ "deleted": id, }) // Handle errors } else { return err } } }
|
以上都是Go后端代码。待续: