📊 Comprehensive Go Web Frameworks Comparison: Gin, Echo, and BeeGo

☁ïļ Introduction

Recently, I have been looking to develop a web application for budget tracking for myself. I have been using Google Sheets to track my budget previously, but I would like to have something more advanced. So, I decided to develop a web application for this purpose.

While thinking about the budgeting web application, I decided to use Go as the primary programming language for it due to the small VPS on DigitalOcean where this app will be hosted and my personal preferences. After working with Go for a while, I think that it's the best language for me.

In this article, I will consider the most popular Go web frameworks and compare them to choose the best one for my project.

☁ïļ Introduction

💎 Frameworks and criteria

I have looked into these frameworks:

My primary criteria for choosing the framework are:

  • Framework simplicity

  • Following a principle of Go minimalism

  • Speed of development

  • Performance

  • Popularity & maintenance

  • Adoption of the framework

💎 Frameworks and criteria

😊 Comparison

CriteriaBeeGoGinEcho

Framework simplicity

Simple and very similar to Django or Spring MVC

Very simple and minimalistic

Very simple and minimalistic

Go minimalism

No, it has a lot of magic like Spring MVC, Django, or Rails

Yes, it has a minimalistic approach

Yes, it has a minimalistic approach

Speed of development

Fast speed of development due to built-in templates, ORM, and other features like in Django

Lower speed of development compared to BeeGo due to minimalistic approach

Lower speed of development compared to BeeGo due to minimalistic approach

Performance

Fast performance but lower than Gin or Echo

Very fast performance

Very fast performance, but lower than Gin

Popularity & maintenance

31.6K stars on GitHub, last commit 4 days ago. However, the documentation website is down and only backup is available

78.8K stars on GitHub, last commit 1 day ago

29.8K stars on GitHub, last commit 1 day ago

Adoption of the framework

Low adoption (by ChatGPT)

High adoption

High adoption

From the comparison table, I can say that Gin and Echo are very similar frameworks in terms of simplicity and minimalism. I worked with Gin in the past in one of my companies, and I can say that it's an excellent web framework for Go.

While BeeGo has a high speed of development, it follows principles of Spring MVC and Django, which is not the Go way. However, it provides a lot of features out of the box like built-in ORM, templates, and others, which are not provided by Gin or Echo by default.

So, I decided to develop small prototypes of web applications for better comparison of these frameworks.

ðŸĪŠ Prototypes of Web applications

FrameworkGitHubDescription

BeeGo

GitHub

Framework's own project structure which doesn't follow the Go way. Built-in ORM, templates, and other features like in Django. No DDD.

Echo

GitHub

Go project structure with FX (DI) and DDD. No ORM, Pongo2 templates (similar to Django templates)

Gin

GitHub

Go project structure with FX (DI) and DDD. No ORM, Go standard templates out of the box

From the developed prototypes, I prefer Gin or Echo due to following the Go way project structure and minimalism. BeeGo has a lot of magic and doesn't follow the Go way, it provides its own project structure which is not okay for me. Also, it provides ORM out of the box, which I don't want to use due to the complexity of maintaining ORM-based projects in the long run.

So, I decided to go deeper with the frameworks comparison and consider HTML templating approaches for them, as I'm planning to render HTML on the server side and have a very simple frontend client.

ðŸĪŠ Prototypes of Web applications

ðŸ˜ĩ‍ðŸ’Ŧ Challenges with template engines

FrameworkTemplate EngineDescription

BeeGo

Custom template engine

The template engine is similar to Django or Spring MVC out of the box. It works well with template inheritance and other features

Echo

No template engine out of the box

Echo doesn't provide any template engine out of the box. You need to use a third-party template engine like Pongo2 or others

Gin

Go standard templates

Gin provides the Go standard template engine, which doesn't support template inheritance for two or more templates out of the box

So, BeeGo has a good template engine, but I decided not to use it in my project. I need to choose between Echo and Gin. There is a diagram depicting what exactly I need from the template engine:

Template engine requirements

I would like to have a base HTML file "layout.html" from which child pages like "dashboard.html" and "report.html" should inherit. This is a very simple problem which has been solved numerous times, but not in Go standard templates 😆.

For Echo, I decided to use the Pongo2 template engine, which is very similar to Django templates and provides template inheritance. However, my concern was with the "very similar to Django templates" part. I just don't need so many features. Go standard templates are very simple and minimalistic, which is exactly what I need. However, they didn't support template inheritance for two or more templates.

🐭 Workaround for Go standard templates

So, I decided to use Go standard templates for my project, and Gin has built-in support for them. Also, the Gin community provides a way to implement multiple template inheritance using the multitemplate library. This library is pretty good, but it doesn't provide an automatic way to load templates in the right order.

So, I decided to fix this problem in the Gin prototype project.

1func NewRenderer(cfg *config.Config) multitemplate.Renderer {
2	renderer := multitemplate.NewRenderer()
3
4	// Load all template types
5	layouts, _ := filepath.Glob(fmt.Sprintf("%s/layouts/*.html", cfg.TemplateFolder))
6	partials, _ := filepath.Glob(fmt.Sprintf("%s/partials/*.html", cfg.TemplateFolder))
7	components, _ := filepath.Glob(fmt.Sprintf("%s/components/**/*.html", cfg.TemplateFolder))
8	pages, _ := filepath.Glob(fmt.Sprintf("%s/pages/**/*.html", cfg.TemplateFolder))
9
10	// Generate template map
11	for _, page := range pages {
12		files := []string{page}
13		files = append(files, layouts...)
14		files = append(files, partials...)
15		files = append(files, components...)
16
17		name := strings.TrimPrefix(page, fmt.Sprintf("%s/pages/", cfg.TemplateFolder))
18		name = strings.TrimSuffix(name, ".html")
19
20		renderer.AddFromFiles(name, files...)
21	}
22
23	return renderer
24}

The code above loads all templates from the specified folders and generates a template map for Gin. The key here is to load templates in the right order and bind them to the page name, which allows rendering pages utilizing page inheritance - GitHub:

1c.HTML(http.StatusOK, "user/profile", gin.H{
2    "User": user,
3})

While this approach is not perfect, it's good enough for my project. I don't need to use third-party template engines, and I can use Go standard templates out of the box.

🎉 Conclusions

I decided to use Gin for my personal budget tracking web application because:

  • Minimalism and following the Go way

  • Performance

  • Standard Go templates support

  • High adoption and popularity of the Gin framework

Also, Echo looks very similar to Gin, but it requires using third-party template engines, which I don't want to use.

🎉 Conclusions