Full stack part 2: Are we going yet?
Right, you can install go on pretty much anything. I have it on my Windows side, but we’ll be using it on the Ubuntu side, so let’s go ahead and install it. Here’s official docs:
To be a bit more comfortable with the installation and setup, after a bit more googling, I found this guy called Nic Jackson on Youtube and he sounds very nice and knowledgeable, so I instantly decided that his way was the most reliable way of going ahead with the installation.
Here’s how he says you should do it too:
https://www.youtube.com/watch?v=poejKP1wTpc&ab_channel=NicJackson
Now I have Go running, and a basic understanding of where to keep my go files. It’s time to start coding the back-end.
A back-end with Go
I’ve been coding with PHP for years, and I don’t think there’s anything really wrong with it. For some reason I’ve never really liked the idea of using Node as back-end, and in terms of running a website, Python is just another alternative and I’ll choose PHP over Python on most days. I’ve built my share of Django websites, and I do like Python as well, but in general, PHP is still really popular, and a major chunk of the internet is running PHP. Not to mention how popular Wordpress (running PHP) is - and I do like WordPress too.
But here we go, a bit late to catch the Go-train. I was supposed to catch this at least 7 years ago and that would not have been too early either. Better late than never though. If you start coding Go, you’ll hear it’s ‘different’, it’s simple, easy to learn. In terms of the advertised benefits, it’s fast and can handle lots of concurrent users. From the few tutorials I’ve gone through so far, it’s definitely different from PHP, but it’s still just another programming language. Nothing scary here.
My opinion
Let’s get one problem out there first. In programming languages, there’s lots of opinions about a lot of things. One difficult thing when starting out is finding out that there’s always multiple ways of doing things. Someone says “Don’t worry, you can do X, or like Y, it really doesn’t matter.”
How about if you want to do it the best way? Well, decide for yourself. But should I not do it the same way as the majority? What’s the best practice?
So in this post, I may not always have found the tutorials following the best practice, or it might not exist. Hopefully the code stays concise and clear.
Packages
Further down the line (or up, depending how you look at it), there’s another level of opinions. In PHP, for example, I might go with a framework like Slim instead of Laravel, when building something nice and small, and it may be fairly easy to decide based on app requirements, what framework would work best. Of course there’s tons of frameworks, and for whatever reasons, I’m usually drawn to Slim, or Laravel. The framework alone, especially in the case of Slim, is not necessarily enough, so we’ll look for packages.
When you search for packages, you’re again going to face the same situation - there’s lots of packages that claim to do the same thing. Which one is best - you’ll again hear a lot of opinions. Pick one! Or write your own - pros and cons here, but sometimes you can’t afford to write your own package.
In Go, I found that as soon as I start looking for a router package and an orm package, the opinions started flooding in, and this time some very strong - can’t use this package, must use this one. Shouldn’t use orm at all, in real world you need to build your own. Well I’m just coding for my own projects, and to learn, so I can do a bit of both: use packages, or not, try out different packages and see which one I like. Keep in mind, the more external packages you use, the more maintenance is required as Go itself and the packages get updates. But writing your own packages will take time - and are you good enough at coding to not make costly mistakes along the way? Someone has spent considerable time coding a router so you can save time and enjoy the extra features compared to the standard http library. Find your own balance and try not to dwell on it too much. If you manage to keep things modular enough, you can always go back and swap things out if necessary.
A bit heavy on the text content, sorry - we’ll get to the tutorial bit soon hopefully. I’m not quite sure how many different types of tutorials I’ll end up going through before reaching some type of base target: something similar to static sveltekit SPA front-end deployed somewhere, connected to a go RESTful API back-end deployed somewhere else, using a MySQL database deployed yet somewhere else, and with front-end authentication with email/password using JWT as well as a Google authentication.
I’ve already done some JWT related research for the next post, but at the moment I’m going through yet another Golang tutorial, so we shall probably begin with that.
We’re building something with a routing package called Fiber. And interestingly enough, that’s the one package that divides users - it’s missing some particular functionality that makes it a no-go option for many. Luckily I’m just trying things out. We’ll come back to other router choices later - namely Gin/Chi/Mux. If not confusing enough yet, in most cases you’ll need to connect to a database, and the choice of orm is similarly a matter of choosing from many great packages, all with their own supporters and arguments for and against. In some cases just against - the DIY approach of connecting to database yourself. I’m leaning towards some sort of middle ground, possibly towards a package called Sqlx, which is just extending the standard sql package and nothing too big. But there’s many packages recommended around the internet, like Bun, or Gorm. Here in the following tutorial we’ll get a taste of Gorm.
Golang API Authentication using JWT Tokens
Here’s the current link to this tutorial - it’ll be outdated soon enough, but as Internet is forever, the tutorial will probably still be there:
https://www.youtube.com/watch?v=X9WULjvgqTY
From the very start the tutorial leaves out a Go command that’s needed. Create a folder for your project and open it in your terminal.
Mkdir go-auth
Cd go-auth
Go mod init tutorial/go-auth
The tutorial will also ask you to install fiber, you can do it like this:
go get github.com/gofiber/fiber/v2
Ok, let’s follow along with the tutorial and I’ll just include any additional thoughts here. I’m not trying to copy paste their tutorial here at all, meet me back here when you’re done with the tutorial, or get bored, or stuck. If you don’t like this one, don’t worry, there’ll be more to follow.
Right. Did any of you get past running the app with connection to the database working? Most of the time there’s a problem right at the beginning. So with the above setup I got this:
[error] failed to initialize database, got error dial tcp 127.0.0.1:3306: connect: connection refused
panic: could not connect to the database
So I googled what the mysql.Open connection string should be and it just would not open, so I decided to wipe the docker containers and look for another way to install mysql+phpmyadmin. After trial and error I got to this page:
https://bidhankhatri.com.np/system/docker-compose-file-for-mysql-and-phpmyadmin/
I copy pasted their code to docker-compose.yml
. (This was not the first I tried…).
(Did I say we’d not be writing any docker files?)
version: '3.2'
services:
db:
image: mysql:8.0
container_name: appsDB
restart: always
ports:
- '3306:3306'
environment:
MYSQL_ROOT_PASSWORD: root
app:
depends_on:
- db
image: phpmyadmin/phpmyadmin
container_name: phpmyadmin
restart: always
ports:
- '8068:80'
environment:
PMA_HOST: db
I changed the mysql ports to be both 3306 and the phpmyadmin ports to 8068:80 as I tend to have something else in 8080 occasionally. The rest I let stay as is.
Ok, now I have them running again, and in phpmyadmin I’ve logged in, created a database called gofibertut. In your main.go the connection string is now:
“root:root@/gofibertut”.
Right. I’ve got past the first error. Back to the tutorial. As a bonus, I have a slightly more portable development environment with the included docker-compose.yml file.
Next issue - the files get split up early on in the tutorial into relevant packages like database, routes and controllers. In this tutorial these get imported with relative paths. But there’s no relative path imports in Go apparently:
https://stackoverflow.com/questions/38517593/relative-imports-in-go .
So, instead, since I created the project with go mod init tutorial/go-fiber-auth
, we’ll import database (at the moment it’s only one file, ‘database/connection.go’), with “tutorial/go-fiber-auth/database”
(instead of “./database” as it happens in the tutorial. Fine, let’s carry on.
API endpoint testing
This time not an issue really, but often there’s a need to ping an endpoint in the back-end and we don’t have a front-end. In this tutorial they’re using Postman, which is good. But if you’re using VS Code, you don’t have to leave the editor - you can just use another extension. I came across Thunder Client, which maybe isn’t as comprehensive as Postman, but it will do the trick here for the time being. Since writing this, they’ve also added Postman as extension to VS Code.
Scratching JWT surface
I’ll get back to the subject of JWTs later on, but for now, let’s carry on with the tutorial.
Maybe the package has been updated since the tutorial was released, so I’ve ran into some trouble while following the tutorial. I need to set Expiry date for JWT token and while it’s bad practice to set it to 24 hours, let’s go with that for now. The issue is with something else:
claims := jwt.NewWithClaims(jwt.SigningMethodHS256, jwt.StandardClaims{
Issuer: strconv.Itoa(int(user.Id)),
ExpiresAt: time.Now().Add(time.Hour * 24).Unix(),
})
Turns out …StandardClaims{..., ExpiresAt:
is type of *jwt.Time, but we’re trying to give it something other (value of type int64). So I’m trying to create the expected variable for the ExpiresAt property. Without any googling, I’ve ended up with: *jwt.At(time.Now().Add(time.Hour * 24))
and the environment is not showing an error anymore. So that’s a start.
Some time later, the tutorial finishes, and we have some kind of starting point for a Golang backend with JWT authentication. The Youtube autoplay throws us into the next tutorial from the same channel, and it’s very conveniently “Svelte JWT Authentication”. So we shall continue with that shortly. But let’s first talk a bit more about JWT.