golang todo实例

来源:转载

之前写过一篇todo实例,是使用python的tornado框架实现的。地址:http://blog.csdn.net/luck_apple/article/details/8814091

最近go更新到了1.4版本,正好也研究来玩玩。

看了几天go基础,然后想找个例子练练手,就想起来遇险写过的tornado的todo了,

直接拿来用go重写一遍,本次没有使用web框架,使用go原生API实现。

go语言基础可以看看电子书:http://download.csdn.net/detail/luck_apple/8412345 (0资源分)

go版本1.4,再看下我的go env:

先看看最终效果吧:

ok,就是这个样子。

上次有人抱怨我没有把数据库表结构亮出来,这次索性使用sqlite数据库,表结构真心很简单:

CREATE TABLE todo (id integer PRIMARY KEY,titletextNOTNULL,finishbooleanNOTNULLDEFAULT false)

再看下工程目录结构:

咱虽然没有使用mvc的web框架,但也得有个mvc的样子,mode,view和controller还是要分分清楚的。

入口为main.go(负责创建web server和路由):

package mainimport ("log""net/http""todo/controllers")func main() {// 静态资源服务http.Handle("/public/", http.FileServer(http.Dir("./")))// 路由http.HandleFunc("/new", controllers.NewTodo)http.HandleFunc("/edit", controllers.EditTodo)http.HandleFunc("/finish", controllers.FinishTodo)http.HandleFunc("/delete", controllers.DeleteTodo)http.HandleFunc("/", controllers.Index)err := http.ListenAndServe(":3000", nil)if err != nil {log.Fatal("ListenAndServer error:", err)}}上面定义的路由,都会执行到TodoController.go中的对应方法

再看看TodoController.go:

package controllersimport ("html/template""net/http""strconv""todo/models")func Index(w http.ResponseWriter, r *http.Request) {if r.Method != "GET" {showError(w, "异常", "非法请求,服务器无法响应")} else {if r.URL.Path == "/" {todos, err := models.QueryAll()if err != nil {showError(w, "异常", "查询异常")return}t, err := template.ParseFiles("views/index.html")if err != nil {showError(w, "异常", "页面渲染异常")return}data := make(map[string][]models.Todo)data["TodoList"] = todost.Execute(w, data)} else {// 404页面,路由不到的都会到这里showError(w, "404", "页面不存在")}}}func NewTodo(w http.ResponseWriter, r *http.Request) {if r.Method != "POST" {showError(w, "异常", "非法请求")} else {title := r.FormValue("title")id, err := models.InsertTodo(title)if err != nil || id <= 0 {showError(w, "异常", "插入数据异常")return}// 重定向到主界面http.Redirect(w, r, "/", http.StatusSeeOther)// 没有return,没有效果,重定向不过去return}}func FinishTodo(w http.ResponseWriter, r *http.Request) {if r.Method != "GET" {showError(w, "异常", "非法请求")} else {// 获取表单参数,也可以这么写// r.ParseForm()// id := r.Form["id"]id := r.FormValue("id")finish := r.FormValue("finish")// FormValue取到的数据都为string类型,将id转为int64类型// strconv.ParseInt(id, 10, 64) 10意思为10进制,64意思为64位intId, _ := strconv.ParseInt(id, 10, 64)boolFinish, _ := strconv.ParseBool(finish)_, err := models.FinishTodo(intId, !boolFinish)if err != nil {showError(w, "异常", "完成Todo失败")return}http.Redirect(w, r, "/", http.StatusSeeOther)return}}func DeleteTodo(w http.ResponseWriter, r *http.Request) {if r.Method != "GET" {showError(w, "异常", "非法请求")} else {id := r.FormValue("id")intId, _ := strconv.ParseInt(id, 10, 64)_, err := models.DeleteTodo(intId)if err != nil {showError(w, "异常", "删除失败")return}http.Redirect(w, r, "/", http.StatusSeeOther)return}}func EditTodo(w http.ResponseWriter, r *http.Request) {if r.Method == "GET" {// 显示edit页面// 本可以将title内容提交至此,但url将会异常难看,还是根据id查询吧id := r.FormValue("id")intId, _ := strconv.ParseInt(id, 10, 64)title, err := models.GetTodoTitle(intId)if err != nil {showError(w, "异常", "查询Todo内容失败")return}t, _ := template.ParseFiles("views/edit.html")data := make(map[string]string)data["Id"] = iddata["Title"] = titlet.Execute(w, data)} else if r.Method == "POST" {// edit后的数据post提交至此处id, _ := strconv.ParseInt(r.FormValue("id"), 10, 64)title := r.FormValue("title")res, err := models.EditTodo(id, title)if err != nil || res <= 0 {showError(w, "异常", "修改失败")return}http.Redirect(w, r, "/", http.StatusSeeOther)return}}// 错误处理func showError(w http.ResponseWriter, title string, message string) {t, _ := template.ParseFiles("views/error.html")data := make(map[string]string)data["title"] = titledata["message"] = messaget.Execute(w, data)}数据库使用了sqlite3数据库,使用github.com/mattn/go-sqlite3软件包

Mac的用户可以试试一款极好的sqlite数据库管理工具:http://download.csdn.net/detail/luck_apple/8436489 (0资源分)

再看看我们的model,TodoModel.go:

package modelsimport ("database/sql"_ "github.com/mattn/go-sqlite3")// 为开发方便,使用sqlite数据库type Todo struct {Id int64Title stringFinish bool}func InsertTodo(title string) (int64, error) {// 数据库path是相对路径(相对于main.go)db, err := sql.Open("sqlite3", "./data/data.db")// 函数代码执行完后关闭数据库,这是个好习惯,我爱deferdefer db.Close()if err != nil {return -1, err}stmt, err := db.Prepare("INSERT INTO todo(title, finish) VALUES(?, ?)")defer stmt.Close()if err != nil {return -1, err}res, err := stmt.Exec(title, false)if err != nil {return -1, err}return res.LastInsertId()}func QueryAll() ([]Todo, error) {db, err := sql.Open("sqlite3", "./data/data.db")defer db.Close()if err != nil {return nil, err}rows, err := db.Query("SELECT * FROM todo")defer rows.Close()if err != nil {return nil, err}var todos []Todofor rows.Next() {var id int64var title stringvar finish boolerr = rows.Scan(&id, &title, &finish)if err != nil {return nil, err}todo := Todo{id, title, finish}todos = append(todos, todo)}return todos, nil}func FinishTodo(todoId int64, finish bool) (int64, error) {db, err := sql.Open("sqlite3", "./data/data.db")defer db.Close()if err != nil {return 0, err}stmt, err := db.Prepare("UPDATE todo SET finish=? WHERE id=?")defer stmt.Close()if err != nil {return 0, nil}res, err := stmt.Exec(finish, todoId)if err != nil {return 0, nil}affect, err := res.RowsAffected()if err != nil {return 0, nil}return affect, nil}func DeleteTodo(todoId int64) (int64, error) {db, err := sql.Open("sqlite3", "./data/data.db")defer db.Close()if err != nil {return 0, err}stmt, err := db.Prepare("DELETE FROM todo WHERE id=?")if err != nil {return 0, err}res, err := stmt.Exec(todoId)if err != nil {return 0, nil}affect, err := res.RowsAffected()if err != nil {return 0, nil}return affect, nil}func GetTodoTitle(todoId int64) (string, error) {db, err := sql.Open("sqlite3", "./data/data.db")defer db.Close()if err != nil {return "", err}// 只查询一行数据row := db.QueryRow("SELECT title FROM todo WHERE id=?", todoId)var title stringe := row.Scan(&title)if e != nil {return "", e}return title, nil}func EditTodo(id int64, title string) (int64, error) {db, err := sql.Open("sqlite3", "./data/data.db")defer db.Close()if err != nil {return 0, err}stmt, err := db.Prepare("UPDATE todo SET title=? WHERE id=?")defer stmt.Close()if err != nil {return 0, nil}res, err := stmt.Exec(title, id)if err != nil {return 0, nil}affect, err := res.RowsAffected()if err != nil {return 0, nil}return affect, nil}至于view,代码就比较多了,不再贴出来了。

代码下载地址:http://download.csdn.net/detail/luck_apple/8436475 (0资源分)

版权声明:本文为博主原创文章,未经博主允许不得转载。



分享给朋友:
您可能感兴趣的文章:
随机阅读: