之前写过一篇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 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"] = 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 modelsimport ( "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资源分)
总结以上是内存溢出为你收集整理的golang todo实例全部内容,希望文章能够帮你解决golang todo实例所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)