Remix is a React framework for building web applications. I used my momentum after learning Remix by building Thankful to rebuild their Jokes app in Go.
In summary, the application is a trivial CRUD app that allows authenticated users to browse and add jokes.
From the Go side, I was pleased by the typing system and how the compiler was helping me explore the language and assisting me towards having a functional code!
The following is the folder structure for the project.
.
βββ html
β βββ auth.go.html
β βββ index.go.html
β βββ jokes
β β βββ index.go.html
β β βββ joke.go.html
β β βββ new.go.html
β βββ layouts
β βββ jokes.go.html
β βββ nav.go.html
β βββ root.go.html
βββ lib
β βββ db
β β βββ db.go
β βββ handlers
β β βββ auth.go
β β βββ handlers.go
β β βββ index.go
β β βββ jokes.go
β βββ models
β β βββ joke.go
β β βββ user.go
β βββ utils
βββ main.go
βββ readme.md
Moreover, this project has 4 different packages:
- The
handlers
package is responsible for all the HTTP side. - The
models
package is responsible for modeling the domain. - The
utils
package is responsible for all the helpers needed. - The
db
package is responsible for all stuff related to the DB.
I must say that this is not a best practice. I am not even sure about this organization. However, this feels ok now.
Learning a new language by building a web CRUD application may seem dull. However, having simple requirements in a controlled scope is powerful to focus on what's more important - learning the language!
Rebuilding the Remix Jokes app in Go allowed me to explore the rich standard library. Moreover, I have a better understanding of packages VS folders VS files. Finally, I got to experience how to integrate 3rd party libraries into my application.
To build a simple CRUD web application, you need an HTTP server, a way to serve some HTML files dynamically, and a mechanism to persist and manipulate your data.
The net/http
standard package helps in serving web requests.
http.HandleFunc("/", Index)
http.ListenAndServe(":3000", nil)
The above snippet enables serving web requests on port 3000
on the /
path by executing the Index
handler.
The html/template
package helps serve HTML templates with dynamic data and reusable layout.
t, _ := template.ParseFiles(files...)
t.Execute(w, d)
The above snippet enables parsing any number of go.html
files and allows for the {{}}
syntax to have dynamic HTML.
Although the Go standard library supports working with SQL DBs using database/sql
, I decided to go with Gorm as the ORM in this CRUD application. The reason is to get a taste of using (install, read the docs, and utilize) external libraries.
type User struct {
gorm.Model
Username string
PasswordHash string
Jokes []Joke
}
The above snippet helps create the user model, which reflects the users
table with a one-to-many relationship.