golang todo实例

前端之家收集整理的这篇文章主要介绍了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,titletextNOT NULL,finishbooleanNOT NULLDEFAULT false)


再看下工程目录结构:


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

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

package main

import (
	"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 controllers

import (
	"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"] = todos
			t.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,"非法请求")
	} 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,64)
		boolFinish,_ := strconv.ParseBool(finish)

		_,err := models.FinishTodo(intId,!boolFinish)
		if err != nil {
			showError(w,"完成Todo失败")
			return
		}
		http.Redirect(w,http.StatusSeeOther)
		return
	}
}

func DeleteTodo(w http.ResponseWriter,"非法请求")
	} else {
		id := r.FormValue("id")
		intId,64)
		_,err := models.DeleteTodo(intId)
		if err != nil {
			showError(w,"删除失败")
			return
		}
		http.Redirect(w,http.StatusSeeOther)
		return
	}
}

func EditTodo(w http.ResponseWriter,r *http.Request) {
	if r.Method == "GET" {
		// 显示edit页面
		// 本可以将title内容提交至此,但url将会异常难看,还是根据id查询吧
		id := r.FormValue("id")
		intId,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"] = id
		data["Title"] = title
		t.Execute(w,data)

	} else if r.Method == "POST" {
		// edit后的数据post提交至此处
		id,_ := strconv.ParseInt(r.FormValue("id"),64)
		title := r.FormValue("title")
		res,err := models.EditTodo(id,title)
		if err != nil || res <= 0 {
			showError(w,"修改失败")
			return
		}
		http.Redirect(w,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"] = title
	data["message"] = message
	t.Execute(w,data)
}

数据库使用了sqlite3数据库,使用github.com/mattn/go-sqlite3软件包

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

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

package models

import (
	"database/sql"
	_ "github.com/mattn/go-sqlite3"
)

// 为开发方便,使用sqlite数据库
type Todo struct {
	Id     int64
	Title  string
	Finish bool
}

func InsertTodo(title string) (int64,error) {
	// 数据库path是相对路径(相对于main.go)
	db,err := sql.Open("sqlite3","./data/data.db")
	// 函数代码执行完后关闭数据库,这是个好习惯,我爱defer
	defer 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,"./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 []Todo

	for rows.Next() {
		var id int64
		var title string
		var finish bool
		err = 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,"./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,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
}

func GetTodoTitle(todoId int64) (string,"./data/data.db")
	defer db.Close()
	if err != nil {
		return "",err
	}
	// 只查询一行数据
	row := db.QueryRow("SELECT title FROM todo WHERE id=?",todoId)
	var title string
	e := row.Scan(&title)
	if e != nil {
		return "",e
	}
	return title,nil
}

func EditTodo(id int64,title string) (int64,err := db.Prepare("UPDATE todo SET title=? WHERE id=?")
	defer stmt.Close()
	if err != nil {
		return 0,id)
	if err != nil {
		return 0,nil
}

至于view,代码就比较多了,不再贴出来了。

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

猜你在找的Go相关文章