Webapp Example

Expected output:

open your task.db file in sqlite3 like this

        [Tasks] $ sqlite3 task.db
        sqlite> select title from task limit 1;
        Publish on github

Now this output should match with the one we see at localhost:8080

After running the file, go to localhost:8080 and localhost:8080/add

file ~/main/main.go

package main

import (

    _ "github.com/mattn/go-sqlite3"

var database *sql.DB
var err error

//Task is the struct used to identify tasks
type Task struct {
    Id      int
    Title   string
    Content string
    Created string

//Context is the struct passed to templates
type Context struct {
    Tasks      []Task
    Navigation string
    Search     string
    Message    string

func init() {
    database, err = sql.Open("sqlite3", "./tasks.db")
    if err != nil {

func main() {
    http.HandleFunc("/", ShowAllTasksFunc)
    http.HandleFunc("/add/", AddTaskFunc)
    fmt.Println("running on 8080")
    log.Fatal(http.ListenAndServe(":8080", nil))

//ShowAllTasksFunc is used to handle the "/" URL which is the default one
func ShowAllTasksFunc(w http.ResponseWriter, r *http.Request) {
    if r.Method == "GET" {
        context := GetTasks() //true when you want non deleted notes
    } else {
        http.Redirect(w, r, "/", http.StatusFound)

func GetTasks() Context {
    var task []Task
    var context Context
    var TaskID int
    var TaskTitle string
    var TaskContent string
    var TaskCreated time.Time
    var getTasksql string

    getTasksql = "select id, title, content, created_date from task;"

    rows, err := database.Query(getTasksql)
    if err != nil {
    defer rows.Close()
    for rows.Next() {
        err := rows.Scan(&TaskID, &TaskTitle, &TaskContent, &TaskCreated)
        if err != nil {
        TaskCreated = TaskCreated.Local()
        a := Task{Id: TaskID, Title: TaskTitle, Content: TaskContent,
            Created: TaskCreated.Format(time.UnixDate)[0:20]}
        task = append(task, a)
    context = Context{Tasks: task}
    return context

//AddTaskFunc is used to handle the addition of new task, "/add" URL
func AddTaskFunc(w http.ResponseWriter, r *http.Request) {
    title := "random title"
    content := "random content"
    truth := AddTask(title, content)
    if truth != nil {
        log.Fatal("Error adding task")
    w.Write([]byte("Added task"))

//AddTask is used to add the task in the database
func AddTask(title, content string) error {
    query:="insert into task(title, content, created_date, last_modified_at)\ 
    values(?,?,datetime(), datetime())"
    restoreSQL, err := database.Prepare(query)
    if err != nil {
    tx, err := database.Begin()
    _, err = tx.Stmt(restoreSQL).Exec(title, content)
    if err != nil {
    } else {
        log.Print("insert successful")
    return err


The homework is to split the code into packages and get it to work, the type definition goes into the types/types.go file, the handler definition goes into the views/views.go, the database read and write methods go into the db/db.go. Make sure that after you refactor the code, that the code runs.

-Previous section -Next section

Last updated