go podcast()

I started a monolith-style web application couple of weeks ago and force to admit that Go is more and more fun to use where I was considering more like Django or Rails before.

For me there was still the templates aspect that needed to be fixed, and I wrote a library for that. The other major place where I was not enjoying myself was the database code, found it way to repetitive for application that had a lot of SQL tables.

We're in a very good place at the moment and the benefits of having a compiled language to build heavy backend web application is great.

Links:

  • dstpierre/tpl - a simple library to help with templates structuring, parsing, and rendering
  • sqlc - I finally surrender, and I like it

As always if you want to support the show you may purchase my courses Build SaaS apps in Go and Build a Google Analytics in Go.

Creators & Guests

Host
Dominic St-Pierre
Go system builder - entrepreneur. I've been writing software systems since 2001. I love SaaS, building since 2008.

What is go podcast()?

15 minutes news, tips, and tricks on the Go programming language.

Dominic:

Hello there. I'm Dominic Saint Pierre and you're listening to Go Podcast. Today I talk about how I think Go is very good at building web application. Hello Gophers. Another solo episode this week.

Dominic:

So I will be, we'll be talking about the state of web development in Go, where I think it's, it's at. And, you know, spoiler alert. I think, I think we are in a very good place these days with, web development to be frank. I will unpack that for sure in this episode, but let's let's just tell the story of, you know, what happened and why I wanted to talk about this. So I I started a small, a small, web project a couple of weeks ago.

Dominic:

You know, nothing, nothing complicated, just just a good old web application that you know that you will have some front end, you know, that you will have some back end. Kind of similar to what one could build in Rails or Django to be frank. So a backend, mostly, you know, mostly CRUD operation, but, you know, with, with some kind of UI for users to do their stuff. And, you know, when I was starting the the parsing of the templates, it's always like that for me. I never really remember exactly how I did that the last time, you know, where, you know, how I structure the directory for my templates.

Dominic:

How you know, how do I make sure that I do have some kind of layouts and view kind of hierarchy, if you will. So where you have a, I don't know, you know, a master page. I don't know how to say that. It's a, I know it's a dot net, dot net word, but, you know, let's say that you have a main template. And in that template, you have some kind of block that the the view that you are currently in is currently filling.

Dominic:

For example, you know, there could be a a title block in the main page or the layout page and some kind of content block or whatever. And inside the view then you you you know, you just define those things. And Go, you know, Go template HTML slash template package is already it's already handling all of that. But I don't know if it's me, I don't know if it's not clear or anything like that, but each time I'm faced with having to decide, you know, how to structure my things and and more most importantly, how to parse those template because you you still you still want to keep some kind of order if it's going to be a project with multiple views. And let let's just make some distinctions right at the beginning.

Dominic:

I'm not talking about a small micro service thing that just do, you know, 3 queries to the database and and have one page. This this is not what I'm talking about. I'm talking about a good old web application that do it all, that do have, you know, probably maybe 100 of tables in the database. So so it's it's it could still it could still be seen as a monolith, but it you know, it's it's it's what I called a web application from the good old days where you don't really need to to extract any microservices at this point because it's not this thing does not need to scale at all. So, so yes.

Dominic:

I mean, because, you know, because we are not all Netflix and Cloudflares and and whatever. You know, those big organization. Sometimes the the project are just a little bit simpler and and there's no theme and there's there's just no need. So at this point, you want to build a web application in in Go. And there's ways to to make that very fun and com and comfortable.

Dominic:

So why why not just use frameworks that are made for that? Like I was saying, Rails or Django or maybe even, you know, ASP dot NET, MVC and whatnot. Well, I want to, I, you know, I want to to stay and go. I I do like I do like that. I think that we are at the place now where we can safely say that the standard library is kind of comfortable enough to at least consider using Go for these types of application.

Dominic:

And myself, I I I've been a a a very strong advocate of of using a standard library. In fact, I I wrote a book in 2,000 18 which the main topic was was mainly death. I mean, you don't really need more than the Standard Library. And if you are, make sure that you understand the implication of a choice of a library or frameworks. And like most people, when I started doing web development in Goa at first, I I used a framework or or it was more a library in that time because I I was coming from you know, I have this, dot net background and I had sometimes a node and things like that.

Dominic:

And it's more common to use some kind of framework. But when when you when you have the richness of the standard library in Go then it's okay to not use a library if you if you don't want to. If you want to, by all means, I mean, go ahead. It's it's not, you know, it's not a super, 1 or 2. It's not a binary choice here, to be frank.

Dominic:

There there's some nuances and whatnot, but I think the the state of, you know, of the standard library HTTP package, Net HTTP is is very good. But for me the templates was kind of still a point that was making me, a little bit uncomfortable. And yes, I yeah. You You know, you you have things like temple. You have other library that that tries to, to make, you know, make a difference in that space.

Dominic:

But I want to stay in standard HTML file. This, you know, I I do have, do I do like the the directives and I do like everything that the HTML template package offers me. What I don't really like was how I needed to remember or at least go find the information on how to really structure those those templates and and have some kinds of pieces of reusable component and whatnot. I mean, it's it's it's not complicated. Don't get me wrong.

Dominic:

But I created a library, for that. And my idea was to let's let's I I I wanted to build something for me. I mean, it's not it's not even something I I expect to have, you know, some kind of traction or anything. It it's just it's just for me that, you know what? This is this is how I think templates should be structured.

Dominic:

This is how the directories and the file names should, you know, should be, should be structured and things like that. And I I I took the, the the time to also incorporate some kind of multi language feature in there. Because at the end of the day this is something in in Quebec that we are faced, often. We are a bilingual province. In fact, the Canada has French and English as the, you know, the main language here.

Dominic:

So I mean, it's it's not it's not very, infrequent to build multi multilingual website in here or at least web application and things like that. So I took the the liberty of doing that and I started as well a an internationalization piece where this this was something that I really like in, in dot net, to be frank. The, the, you know, all the culture and and the local when you were displaying dates and currencies, that was good. So I I kind of started that. The idea of just using some kind of, of fun function in in the func map of the template.

Dominic:

So basically, the the library is kind of opinionated on how you should create your your directories and and, you know, the file names and things like that for the for the views. But once you adapt this, it's pretty much out of your way because at the end of the day, it's basically just using the HTML template to do its thing. So, I've also added, an x XSRF token in in there. So basically, there's there's a struct that is passed to all of the views. And normally when when you execute the template, you just pass some data which is an interface.

Dominic:

But now there's a type in in this library that that do have the language, the local, the you know, there's a data as well. So the normal structure that you would pass is also encapsulated in that structure. But there's there's also an NXS RF token field and things like that. So I'm just trying to give some order and discipline to myself with the the templates aspect. Because I after after creating some some web application in the in the last 6 months and and so in in Django, I kind of found it interesting, you know, how the the views or, you know, well the the templates or whatever.

Dominic:

It's it's, there's a lot of helpers in there and things like that. So we do have the func map that is a great way to enrich all the directive that we already have with HTML template. And, and yes. I'm I'm, I'm planning on on using that that library to do that. And, and yes.

Dominic:

I mean, if if anyone want to check it out, it's it's on GitHub. I will, there's a link on the show notes. It's, it's it's, this API slash tpl. So I call it tpl. So for me, this this kind of handle all the structuring, the parsing and the rendering of, of HTML Template without me having to, to return to my old project and say, oh, you know, how did I did that?

Dominic:

How can I have some partials that that are are parsed with my template? But I saw I also want a layout page for my for my templates and things like that. Because at first, at some point, what I was doing for smaller projects because the way that the HTML pa template package is done, there there there were a couple of ways to just, you know, have to repeat the HTML and the ad and the title and things like that in in all your templates. Basically, this is that was maybe the way to go a long time ago, but they, I I think it was with Go, I believe, 1.8 that they introduced the, the block and the define key directive in theirs. But, but, but even that, even that, you know, just having to remember how to parse your layout with all the pages and things like that.

Dominic:

So so I I I kind of enforce a directory structure where let's say you want to have 2 or 3 different base layout. Let's say you you want a layout when the user is not authenticated and one when when they are. So basically, you can have a layout page called, I don't know, you know, not authenticated dot HTML and authenticated dot HTML. And inside of views directory, you can create 2 subdirectories with unant unauthenticated and authenticated which which match directly the name of the layout and the pages that that are saved there will be parsed with the layout and all of the the partials things. So let's say, you know, let's say you want to to reuse some HTML component here and there, like, a main navigation or maybe it's a footer or it's it's it could be, I don't know.

Dominic:

It it could be any anything that that just can be rendered, and this will also be parsed with all the views. So it it's just, you know, it's nothing. It does not bring more much to the table for for only that. But just to remove the, you know, the fact that I need to the cognitive load on me to remember all of this this crap. Because let let's face it.

Dominic:

It's not it's not very fun to to just, to just have to do that each time. So I wanted an helper. If if it helps anyone, cool. If not, well I'm using it which is why I I did it. So so that's that.

Dominic:

But I also think that, you know, having some kind of of locale and some kind of dates and currencies rendering with the proper, you know, the proper, currency symbol and whatnot and the proper way of formatting the decimal. No. The this this could be a this could be a nice helper. So that that's it for for the template. And now, I mean, the second pieces for me, that they really nailed down in in 1, 122, you know, is, obviously the new I won't say I won't say the new the new routing feature because at the end of the day it's it's just a way to it's just a way to to to name your your your path directly in in your Endel func or Endel function.

Dominic:

And and that that is great. I mean, first of all, if, if you if you haven't seen that, you know, there there there's not much need for a router these days due to that. And a lot of people will probably say, well, the router comes with a lot of middlewares and things like that. Middlewares are just, you know, one function, couple of lines of code long. So do you really need to, to bring an external router for that now that we do have parameterized URL?

Dominic:

And also we can we can bound a specific, a specific Endelphonic with, with a verb now. So you can prefix your roots with something like post for example. So you would say, I don't know. You know, http.endolfnkopenparenquotethedoublequote. You you would have posts and you know slash blog for example.

Dominic:

And or or slash blog slash create. And if you were to to do an HTTP GET to that you will automatically get a meta meta not allowed HTTP status for for that. So not a huge change but I mean it's it it it did not really bother me, to be frank, in the, in the previous version where you could do all of the HTTP verb on the on the specific path, if you if you will. I was I was kind of mostly using an if, an if block. If I knew that I was going to be receiving some some, HTTP post in there, so I would do, you know, if r.metal equal HTTP dot metal post, for example.

Dominic:

But now, I mean, it's it's built in in there. So not not a huge change. Not something that that that will change my life as a back end developer. But it's it's it's nice. It's nice to have that.

Dominic:

The parameter URL. The, you know, the fact that you can now put some values in in this with, with braces. This is great. But again, I mean, I I I I was just having a one function preview previous to that. Something called like, I don't know, get URL params and I was passing the request.

Dominic:

And from that I was I was extracting. So I was extracting, the value at certain positions. So I was calling this get your app around, I was passing the request. And the second parameter would be, you know, what position you want the value of. So, if you can imagine a path separated by slash.

Dominic:

So slash blog slash create. If you want the second parameter you will you would get create. So if we were to have blogdetailone, you know, you would call this function with with with the request itself and and tree and you would you would receive the string the string 3. The string 1, sorry. So again it it it's just a small quality of life.

Dominic:

Now you can just do, you know, there's a path value in, on on the request structure itself, the HTTP request. And now you you can just you can just receive or call or get the value by the name of the parameter. So if you have if you have slash blog slash detail slash brace ID for example you can do r dot path value ID. So this this this is great. Again, not throwing me out of my chair or I don't know how to say that.

Dominic:

We have this saying in French but, well, in French, but in in Quebec, actually. Without entering into too much history and geographical things, I am not a French from France. I am a French Canadian from Quebec. So we do, we do speak, very very differently. So so you know, closing this, this aside.

Dominic:

So I I mean yes. So this is not super I don't know. I cannot say that. It's it's not going to revolutionize, how you do things. It's just some quality of life.

Dominic:

And for me, the template was still something that was was not polished enough for me to to say when you have a very quick CRUD application to build you can do that in Go instead of Django or Rails. But nowadays, I believe that I believe that it is possible, to, in terms of times. And the last piece that that I finally decided to use is SQL c. And I've I've I've done an an episode on on databases, very, very early in in it was probably 2 years ago. I think it was episode 4 or 5, whatever.

Dominic:

For me database it always felt a little bit too verbose in Go. And I'm not a fan of ORM as well. So I've been I've been doing data all my career. I've been, you know, living in in SQL, all my life. So for me, it's not about typing queries.

Dominic:

I'm not I'm not talking about having to type SQL queries. I'm talking about all all the database SQL was makes you, repeat yourself a lot. If you if you don't want to to use Reflection and or or other libraries like, SQLX, for example. So I always look at SQL C and I was this is interesting, but I don't know. I mean, it it it felt strange to use an external tool to generate Go code.

Dominic:

But I yeah. I tried it, very very, you know, I more thoroughly, lately and and this is great. This is probably the missing pieces for me for, you know making sure that I do have fun writing some simple web monolith application in Go, because now I can I can just write and I can just write my my query in SQL and and and let this tool generates all the repetitive stuff that I I did not really mind? And then what I was doing previously was I created some, some snippet in Versus Code, to be frank. And I was I was, you know, something like, DB create.

Dominic:

I was doing tap tab and boom. It was it was just generating the structure, and I I could just fill the blank, if you will. So for me, it was it was still kind of quick to create database access code, but it was not fun. It was certainly not fun. And after after that, when it's not fully generated, if you have part of your application that is that is not fully generated and you you do have a lot of repetition, if something is to change then it means that you you have a lot a lot to change.

Dominic:

So I kind of tried to be a little bit more open minded and and just just tried the thing because I tried the POG base back in the days in, I think it was in Closure, if I'm not mistaken. One one of one of my friend started to to write some Closure at some point, and I I I was curious. So I I did that for a couple of months. And, and there there were there were the the same kind of of idea there that you you were writing the SQL queries outside and the code was generated. This is great.

Dominic:

So so with the templates out of the way and now the database, you know, it's it's pretty quick to write your, your queries. Just do a SQL c generate and and you you're done. So I I I enjoyed that. My last piece was to fix, you know, how to fix the the SQL migration. And and for for that, I need I decided to just use my own logic which which is so simple.

Dominic:

I mean, when you think about that, what is a migration? Do I really need all of this going down route? So I I I just I just, you know, created a a super simple table in Postgres that do have some, some field, a version field. I do have a directory where I'm going to create a SQL file with with some, you know, with 4 digit at at the at the beginning of them. And I'm I'm just, you know, I'm just checking in the database, you know, what what is the last version?

Dominic:

What is the last version in in this directory? And if there's anything new, then I'm running a transaction on the database and I update the version on that's it. I mean, it's less than, I don't know, it's less than 40 line of code. Did not really needed more. I I I wrote something like that for a static backend actually.

Dominic:

So, yeah, I decided to to just do that. So now I I do have a very kind of easy way to upgrade this schema. I'd I'd that that's that might be one thing that I I'm not fond of. And I I think that that is mainly why I was not using SQL c is is the the schema file to me. I I would still prefer if if this thing was, you know, just looking at the database for for the schema.

Dominic:

That that would be, I don't know, for me, that that would be less of a pain if you will because because now you have you have to maintain this file. I it's it's just a little bit strange to me. I I would have done something like, you know, just just look at the database, inspect. May maybe have some kind of reference somewhere that you can compare the schema on the database. If if anything changed then then, you know or or just generate always based on the on the database.

Dominic:

That that could be that could be simpler. I don't know. I'm still I'm still unclear why we are required to have this schema file to be frank. Because it's not it's not handling the migration, so it's imply that you will have some kind of solution already for migration. So, why bother having a schema file then?

Dominic:

If the database is going to be upgraded and migrated itself from somewhere else, then would it not be, you know, simpler just to check the database for the schema instead of having this this flat file on the project. So that that that was that was a blocker that I had. But, you know, it's not it's not the end of the world to be frank. But I mean, yeah. Something, some some sometimes you see something that distracts you or bother you and you don't really you don't really want to use a library or a tool.

Dominic:

So for me, it was that. It was not it was not really writing the sequel. Although I'm already starting to think that, you know, having having one file and maybe maybe there's a way to have multiple files, you know, it's it's not like I have read the entire documentation of SQL c, but I can see myself having having some, some difficulties accepting to have only one file because at the end of the day, it it will probably just get very verbose out there. If, you know, if if we retake this example of having a web application with 100 SQL tables, for example, you know, how many queries would you have? If if you if you are to start to having, I don't know, 4 100, 500 queries in that file, I mean, I I would still prefer to separate those probably per table or per, you know, use case or anything like that.

Dominic:

So maybe maybe it's something I would I would add to my make file. Just cat some, some separate file into this query, dot SQL dot SQL C is one thing. So I would basically just do that to keep some kind of order in in my in my SQL queries because, yes. I I don't know yet. It's it's not I'm not there.

Dominic:

I only have a handful of queries now, and I'm still under 20. But already I can start to see that having just one file is going to be interesting. But again, maybe maybe it's already done. I don't know. The fact is, yeah.

Dominic:

I I think we are in a very, very good place now these days. And, to to be to be frank, yes. I don't believe that Go is is to be rejected, right away for simpler project and and and crowd the, you know, monolithic CRUD I like app application web application. It's now it's now pretty quick to do that and almost entirely with the the standard library. And I would not even count SQL C as as a dependencies as it it's a it's an external tool.

Dominic:

So it's it's a dependencies in the sense, but it's not in my Go mod, for example. So I don't have these dependencies in my project per se. So I kind of like that. So yes, I mean, we we are we are good. So where where are we going from here?

Dominic:

I mean, it's, it's it's just nice. And and it's the same, you know, it's the same benefits for for doing microservices. So I I mean, those, those new addition in 1 22 for for all the routing and and stuff. It's it's nice. And, and returning to middleware.

Dominic:

I mean middleware is is just a function that accepts the an HTTP handler and return an HTTP handler. And you can you can chain those very very easily with with just a a four line of code functions. So that is that is your middleware there right away. So I don't really, I don't really see any anything complicated and and this makes you a a better web back end developers. Just having to think about how to, you know, how to architect that and and yes I will I will need my authorization middleware before this and that and things like that.

Dominic:

So you you are kind of responsible of of building your web application the way you want. I think this makes projects, you know, a little bit long long a longer live and easier to maintain. The less dependencies that you have, the less complex complicated time or at least the the the time to get used to a project is is lower because everyone is know is knowing you know, all Go developers knows about the standard library. So, so again, I mean, that's it, that's it for this week. I think if you, if you want to to try it out, I might have some kind of blog post.

Dominic:

Maybe I will have some videos. I I do have a YouTube channel that I'm trying to revive. So, yeah. I might have some more content about that because I think, I think we are in a very, very good place without having to bother with the burden of having a frameworks and this is great. On that, see you next time.

Dominic:

Alright. That's it for this week. I would really appreciate if you can talk or share about this podcast. It's always helpful. Also, another way to support this show is by purchasing my course.

Dominic:

There is always a link in the show notes. So on that, see you next week.