Build a Simple To-Do List App in Golang
By: Mohamad Fadhil
Tags: Golang, Api Development, Tutorial, Programming, Software Development

Let’s Begin

1. Bootstrap a project

First, let’s create a new directory and install gorilla/mux and logrus packages in the directory.

$ mkdir todolist-mysql-go

$ cd todolist-mysql-go

$ go get -u github.com/gorilla/mux

$ go get -u github.com/sirupsen/logrus

Now create a todolist.go file with the following content:

In lines 3-8, we’re importing all the necessary packages we get in our previous go get -u commands. Beware that you’ll get a compilation error when importing any package in Go code without actually using it.

In lines 10-14, we created a Healthz function that’ll respond {"alive": true} to the client every time it’s invoked.

In lines 16-19, we set our init function to set up our logrus logger settings. In Golang, init() will be executed when the program first begins. You can read more here.

In lines 21-26, we’re initializing our gorilla/mux HTTP router with a walrus operator. We route /healthz HTTP GET requests to the Health() function. The router will listen to port 8000.

It’s important to set the Content-Type: application/json so the client software understands the response.

Simple enough, right? Let’s see what we’ve got so far.

Great! Our first endpoint is now live.

2. Connect to the MySQL database

Before connecting our Go app to the MySQL database, first we’ll need to have our MySQL server up. We’ll be using Docker, in this case, to launch a MySQL container and expose the port 3306 to the localhost . We’ll create a todolist database in the MySQL container.

$ docker run -d -p 3306:3306 --name mysql -e MYSQL_ROOT_PASSWORD=root mysql

$ docker exec -it mysql mysql -uroot -proot -e 'CREATE DATABASE todolist'

Back to our Go app, we’ll need to install the GORM libraries and dialects.

$ go get -u github.com/jinzhu/gorm

$ go get -u github.com/go-sql-driver/mysql

$ go get -u github.com/jinzhu/gorm/dialects/mysql

Add these lines in our todolist.go code:

Add our new imports into the import list in lines 8-10. In Golang, if you don’t intend to use the variable, you have to name it _ . You can read more here.

Next, we’ll initialize our MySQL connection to our database using GORM. The following lines are to check if there’s an error connecting to the database. If there is, log it.

defer db.Close() means we’ll close our database connection when our main() function is returned.

3. Auto migrate the TodoItem ORM model

GORM comes with a neat database automigration feature, where it’ll create a database table based on your struct definition in the code.

Our TodoItem struct will consist of:

Id int : This will be our primary_key

: This will be our Description string : This is what we’ll display in our front-end UI

: This is what we’ll display in our front-end UI Completed bool : This is to determine if the TodoItem is done or not

Add these lines to your Go code:

In lines 7-11, we’re defining the TodoItem model as what we described earlier. Everything here is self-explanatory.

In lines 19-20, we’re running automigration against our MySQL database immediately after starting our API server. See it in action here:

Yay, our database is ready.

4. Create TodoItem operation

Add the following lines in our todolist.go file:

On line 16, we obtain the value from the POST operation with r.FormValue("parameter") . We use the value as the description to insert into our database. After that, we create the todo object and persist it in our database. Lastly, we query the database and return the query result to the client to make sure the operation is success.

In line 32, we register the new route /todo with an HTTP POST request into our new CreateItem() function.

5. Continue with the rest of the CRUD operations

Let’s continue with the rest of the Read , Update , and Delete operations.

We should be able to perform Create , Read , Update , and Delete operations on the TodoItem s.

In order to update a TodoItem object, we’ll first query our database to ensure the item actually exists. I created a function, GetItemById() , for this purpose. The equivalent SQL query is SELECT * FROM todo_item_models WHERE Id = <Id> LIMIT 1; .

Both UpdateItem() and DeleteItem() functions will invoke GetItemById() first before actually updating or deleting them.

Notice I imported the strconv package in there. The package is used to convert the String variable into an Integer before we run the SQL queries.

The GetCompletedItems() and GetIncompletedItems() functions are self-explanatory as well. It’ll execute a SQL SELECT query and encode it into JSON before returning it to the client.

6. Connect with the front end

In order to connect the API server to the front-end page, we need to give the CORS headers to the response. CORS is a mechanism that allows restricted resources on a web page to be requested from another domain outside the domain from which the first resource was served.

To do so, you’ll need to install the Go cors package.

$ go get -u github.com/rs/cors

Add these lines to your Go code:

In lines 28-32, we’re wrapping the CORS handler around our existing application.

Now clone my front-end site for this Go app.

Then, open the index.html page in your browser. There’s nothing special in this simple jQuery page. I’ve modified the original code made by themaxsandelin to execute AJAX requests when you click buttons in the page. Check the resources/js/main.js file to see how the web front end works.

7. Build the package

Now we’re done with our coding. You can now compile your code.