Get in touch
In this three-part blog series, we want to introduce you to Flamingo, the modular open-source framework from AOE based on Go, step by step. Look forward to exciting deep dives into the Go programming language, interesting facts about the pros and cons of development frameworks in general, and in the third part, plenty of information on how you can set new standards with Flamingo for creating customized, fast, and flexible web applications.
Start right now with Part 1: The Language Choice: JUST GO FOR IT!
Any new programming language gifts its creators a blank slate, with the chance to crystallise the experiences and lessons learned from older languages into an evolved solution. Freed from technical debt, they can also focus on building a language that focuses more cleanly on contemporary, modern infrastructures, technical challenges and requirements.
Go emerged from the ultimate thoroughbred stable. It was initially developed within Google by a highly experienced team of programmers including Robert Griesemer, Ken Thompson (the designer and creator of both UNIX and C) and Rob Pike ( a co-creator of UTF 8 and UNIX). The language was first launched as an Open Source project in 2009.
As such a relative youngster, Go is a programming language built for an era of: cloud computing, containerisation, service based architectures and DevOps. At the same time, its creators wanted to focus on the scalability (in all senses of the word) and the ease-of-use of the language itself. Learning the lessons of the past, Go is built on a mantra of “one problem - one solution”. This typically works out as far fewer solutions to any problem, but still serves to both simplify learning the language and unify programming opinion across large, multi-team programming environments. The end result has been an attractive new combination of powerful, contemporary technical features, that are underpinned by a philosophy of simplicity.
The counter-side to all this zesty freshness is that the success of any language is a direct function of: developer adoption, broader community and a thriving ecosystem (tools, libraries, etc.). With any new language, all of this has to be built from scratch. Whatever the technical merits, early adoption is typically stuck in a vicious circle: developers cannot justify the cost of honing new skills with no market demand, and corporate adoption is rendered too risky with a lack of relevantly trained developers.
In under 15 years, Go has convincingly broken out of this: creating its own meritocratic circle of hyperscalers, start-ups and now enterprise users. Adoption from within Google and companies such as Uber, SoundCloud and Dropbox, created an early pool of Go talent trained and experienced in the intricacies of hyperscale Web application development. The most innovation-hungry developers saw Go as a route into this exciting, bleeding-edge playground. Natural career movements from within this early talent pool, then saw Go permeate further out into the world of start-ups.
This lofty start amongst the hyperscalers and unicorns, in turn, made Go attractive for the most pioneering enterprises. The inherent strengths of the language combined with an attractive pool of developers offering unmatched experience in scaling web applications using the latest techniques and methodologies. And for these enterprises looking to emulate some of the Hyperscaler success: an increasing number of their best developers wanted to start new projects in Go; and starting new Go-based projects offered a route to attracting more experienced, top talent.
Early enterprise adoption of Go was certainly a bold move. It was undoubtedly more risky than continuing projects with more traditional languages: there is always the risk of a hype bubble around the latest developer technologies, and recruiting and keeping hold of talent was harder from a limited and very in-demand pool of developers. However, for most, the risk paid off.
As a result, Go has rapidly carved-out a substantial niche in software development circles and become an established enterprise technology. Much of the adoption risk has evaporated, while the benefits have continued to grow. Go is now consistently ranked in surveys as one of the fastest growing and most in-demand programming languages year-on-year. And, while surveys ranking language popularity are notably inconsistent, even the bolder estimates, ranking Go well-within the top ten languages, understate the true popularity of Go within its chosen niche of high-end, at-scale web application development.
“uld” and Go’s emphasis on simplicity and readability make the language highly attractive to many developers. Importantly, this simplicity also dramatically reduces the learning curve for both new developers and converts. Go boasts a clean and uncluttered syntax, making it easy to learn and ensuring that code remains readable and maintainable. This simplicity is a breath of fresh air compared to the complexity of some other programming languages, especially those offering the same run-time performance level as Go. Languages such as C, Rust or indeed Java have abandoned terseness of code in exchange for developer expressiveness; to use an analogy, they are the CISC to Go's RISC.
In addition to the syntactic sugar that Go offers, it is hard to understate the value and comprehensive nature of Go's standard library. It is arguably one of the most complete standard libraries in any main-stream language. And for more straightforward applications, it is potentially the only library a developer needs. From string manipulation to a complete HTTP client and server, the Go stdlib offers a staggering breadth of functionality.
While the language and stdlib offer considerable power to a developer, it would not be half as appealing without the impressive array of developer tooling that ships with Go. These tools also follow the Go philosophy of simplicity and standardisation. The go fmt tool allows developers to adopt consistent and standardised formatting across a Go codebase. Package management is streamlined with go get, facilitating easy downloads and installations of packages and dependencies. go doc allows developers quick and easy access to documentation, and finally, go test encourages practices like test-driven development (TDD).
The combination of language, stdlib and tooling makes Go a fantastically productive language from a developer’s standpoint. By adopting a philosophy of standardisation and simplicity, Go takes a great deal of the ‘grunt work’ out of developing, allowing developers to focus more on delivering features rather than arguing the toss-over formatting or which testing tool to use.
But Go is not just a win for the developer experience. Beyond offering developers a delightful and efficient workflow, it also packs a punch in performance. Go's knack for compiling straight to binary, sets it leagues ahead of interpreted languages like Python or Ruby. It is fast enough to hold its own against JVM stalwarts, yet it does so elegantly without lugging around an extra runtime. In the vibrant world of containerisation and edge computing, this efficiency is not just handy – it is a game-changer.
While raw execution performance is important, it is not the whole story. Speed is not the only factor at play; performance is also about intelligent multitasking. Enter goroutines and channels – Go's lightweight, nimble threads that the runtime handles with aplomb. This setup is not just a minor tweak; it revolutionises how developers write concurrent programs. Goroutines make complex tasks manageable and let developers craft scalable and efficient applications without breaking a sweat. In the bustling world of web applications, where juggling multiple requests is the name of the game, this gives developers a serious leg-up when it comes to high-scale web applications.
As a result, Go has also found a productive space in the web application space, generally being used to create high-performance and scalable REST, GraphQL or GRPC endpoints.
As with any backend solution, API endpoints are typically communicated via a client application written in whichever Javascript variant is popular at a given point, and this works undeniably well. However, leaning on the features outlined above, Go offers greater flexibility for alternative Frontend architectures.
Modern enterprise applications are required to work well across an increasing variety of devices, screen and screenless formats, different frontend apps, use contexts and integrations into third party applications. This has led to the increasing adoption of backend for frontend (BFF) patterns or architectures: where organisations maintain separate APIs, optimised for different frontend applications, and often take more device-specific processing/pre-processing back from the client onto the backend API.
The separation of APIs in a BFF architecture can dramatically simplify feature roll-outs avoiding the need to manage one complex API release cycle across divergent client apps and devices. It also enables more specific performance optimization. Moreover, features , upgrades and fixes can often be implemented within the API, avoiding the renowned difficulties of getting users to upgrade client software. And from a fault tolerance perspective, app/device-specific problems such as bugs or DDoS attacks can be managed by switching off one relevant API rather than needing to shut down the application for all users.
Not only is Go is ideally suited for developing and maintaining the fast, clean, use-case-oriented APIs, (as we will see below) the clean architecture encouraged by the correct enterprise framework makes it an even better fit for BFF implementation.
For organisations that want to go even further, Go can go even allow developers to create full-stack web applications. Its performance advantages, allows Go developers to create fully featured server-side web applications that can perform and scale as well as any Javascript application talking to an API. This means that an organisation no longer have to maintain two distinct dev teams, backend and frontend, both with entirely different tooling, languages, and often deployment methodology.
For teams that embrace this approach, it can massively increase the speed of product innovation, as there is no more ‘lobbying over the fence’ between backend API features and front-end integration. One team delivers both.
Until recently, this would have been seen as being a deeply old-fashioned approach. Perhaps it is; however, as the increasing popularity of tools such as Hotwire or HTMX shows that, even though something might be “old-fashioned”, it can still offer a valuable start point for modern innovation. Using Go as both the front and back-end language means you gain all the advantages of Go without needing to skimp on features.
Finally, when applications enter production, Go's design philosophy prioritises performance and efficiency, which translates into better resource management and lower overhead when running applications. This efficiency is partly due to Go's compiled nature, meaning it converts directly into machine code that the hardware can execute, as opposed to Python or PHP which are interpreted at runtime. This can lead to significantly faster execution speeds and reduced latency, a critical advantage in real-time application scenarios.
Additionally, Go's robust standard library and its simplicity in handling concurrency with goroutines mean developers can write highly scalable and performant applications with less complexity. In contrast, Python's Global Interpreter Lock (GIL) can become a bottleneck in multi-threaded applications, and PHP traditionally lacks a built-in model for concurrency, relying instead on multi-processing or extensions like pthreads.
When it comes to deployment, Go's static binary compilation is a game-changer. Each Go application compiles into a single binary with all dependencies included. This simplifies the deployment process tremendously since there are no dependencies to manage at runtime, unlike Python or PHP applications that may require a specific runtime environment or external dependencies installed on the server.
This characteristic of Go aligns perfectly with the principles of containerization used in Docker and Kubernetes. The smaller footprint of Go binaries facilitates quicker startup times and less overhead when scaling applications across containers and services in a Kubernetes cluster. The ease of deploying these compact, self-contained binaries streamlines the continuous integration and deployment (CI/CD) pipelines, enhancing overall productivity and reliability in deployment cycles.
Did you enjoy our blog post? Then stay tuned for the second part the series, coming next week. And of course, don't miss the third part, 'Introduction to Flamingo'! If you have any questions in the meantime, feel free to contact our AOE development team here.