Introduction to Go: why Go?
Choosing a language involves more than liking its syntax. Understand how Go balances simplicity, teamwork, and backend development.
Introduction to Go: why Go?
Matt Holiday · Go Class · English · 6 min 28 sec
Watch on YouTubeWhat will you learn?
- Understand the problem Go addresses.
See how simple syntax and shared conventions help a growing team read, change, and maintain code.
- Understand three core mechanisms.
Compilation prepares code for execution, garbage collection reclaims memory, and concurrency organizes progress across tasks. Distinguish the role and limits of each.
- Explain your language choice.
Identify the benefits and costs of Go in a real backend scenario, and decide what to measure before choosing it.
The engineering problem behind a language choice
Imagine you are building a backend service that accepts orders. One person writes the first version. Over time, more engineers join, traffic grows, and the service receives regular updates. Writing code that works is only part of the job. Other people need to understand it, change it, and release it reliably.
This is a useful way to approach Go. Its goal is not to give programmers every possible way to express an idea. It aims to reduce recurring difficulties in everyday software engineering: complex codebases, long waits, inconsistent coding styles, and the need to coordinate several tasks.
Robert Griesemer, Rob Pike, and Ken Thompson began developing Go at Google, and it was released as open source in 2009. The official language name is Go; Golang is a common name in searches and conversation. More important than the date is the motivation: helping large teams manage large programs.
Simplicity should help the person reading the code
You write a function once, but people read it repeatedly during reviews, debugging, and later changes. If finding out why an order was rejected requires tracing five files and several hidden rules, even a short piece of code can be expensive to maintain.
Go encourages explicit control flow and small, concrete responsibilities. A reader should be able to follow where an operation begins, which data it uses, and how it reports failure. Simplicity does not mean the problem is easy. It means the solution avoids unnecessary complexity.
Shared team conventions are part of this approach. Standard formatting reduces discussions about spaces and braces during code review. Engineers can focus on more useful questions: was the boundary case checked, was an error lost, and does this responsibility belong here?
- Names should show intent.
A function's name should make its job clear. For example, calculateTotal indicates a calculation; process forces the reader to look inside the function.
- Make responsibility boundaries visible.
Small interfaces and clear data flow help show which parts a change will affect. Separate calculating a payment from sending it.
- Do not sacrifice readability for fewer lines.
A few explicit steps can be easier to understand than one compressed expression. Readers should not have to guess how the result was produced.
Compilation, types, and memory management
Go is statically typed and compiled. Static typing helps check which operations are valid for a value before the program runs. It does not catch every error: an incorrect business rule or an unavailable database can still cause problems during testing or execution.
A typical Go program is compiled to machine code for its target platform. The program also includes a runtime that handles tasks such as garbage collection and goroutine scheduling. Saying that Go does not require a virtual machine is different from saying it has no runtime.
The garbage collector reclaims memory from objects that are no longer reachable. This reduces manual memory management, but it does not remove resource management. Open files, network connections, and tasks that never finish still need attention. If you keep unnecessary data in a collection, the program may still consider it reachable.
| Feature | What does it help with? | What does it not guarantee? |
|---|---|---|
| Static typing | Catching incompatible type operations early | Correct business rules |
| Compilation | Preparing machine code for execution | Automatically making every program fast |
| Garbage collection | Automating part of memory management | Closing files and connections on time |
Concurrency: making progress while waiting
An order page reads prices and stock levels from two separate services. If it can start the second request without waiting for the first response, coordinating the requests may reduce the total wait. The benefit comes from overlapping independent waits, rather than making the processor calculate faster.
Concurrency means organizing several tasks so they can make progress together. Parallelism means executing work at the same time, for example on different processor cores. Concurrency is possible on a single core. Each waiting operation does not need its own core.
The slides also identify the move to multicore processors as one reason for this need. To benefit from more cores, a program's work must be divided into suitable parts.
Go provides goroutines and channels to organize this work. You can think of a goroutine as a lightweight unit of execution and a channel as a way to exchange data and coordinate tasks. We will cover their syntax in later lessons. For now, focus on distinguishing independent work from steps that depend on one another.
Two independent requests, one response
The price request takes 200 ms and the stock request takes 300 ms. Change the execution mode to compare the total wait.
Sequential: 200 + 300 = 500 ms
Teaching model: the requests are independent and the timeline spans 500 ms. Scheduling and response-combining costs are excluded. These are not measured Go benchmark results.
What does Go offer for backend and cloud work?
A backend service often accepts a request, retrieves information from other systems, processes it, and returns a response. Network waits, simultaneous requests, and operation lifecycles are central concerns. Go's execution model and standard library provide a useful starting point for this kind of program.
Consider operations, too. The team running a service needs to know which file to deploy, what configuration it needs, and how to stop the program. Many Go applications can be delivered as a single executable. This can remove the need to install a separate interpreter.
A single executable does not mean all dependencies disappear. Certificates, configuration, static files, and sometimes system libraries are still needed. Databases and external services remain outside the program. Distribution may become simpler, but responsibility for operating the whole system remains.
- HTTP services.
Accept a request, gather the required information, and return a response. For example, an API that shows an order's status.
- Command-line tools.
Perform a recurring task with one command. For example, a tool that checks configuration and reports the result.
- Background workers.
Take a task from a queue and process it without making the user wait. For example, a process that emails an order confirmation.
- Infrastructure tools.
Automate service and resource management. For example, a tool that checks service health.
When is Go a suitable choice?
Speed and popularity alone are not enough to choose a language. Consider the problem, available libraries, team experience, and how long the system will need maintenance. Go may be a good candidate, but that does not make it the automatic winner.
For a small service that calls several external APIs, straightforward distribution and a clear concurrency model can be valuable. For a small change to an existing Java system, introducing a separate Go service may add monitoring, deployment, and maintenance work. The benefit of the new language should outweigh that cost.
Hard real-time requirements, close interaction with specialized hardware, or reliance on a particular scientific library require further investigation. Do not choose a garbage-collected language for an environment with guaranteed deadlines without measuring its behavior. Rewriting a solution already available in another ecosystem is not always a sound engineering decision either.
| Scenario | Which question determines the decision? |
|---|---|
| A network-heavy service | Are operations independent, and how will concurrent requests be limited? |
| A small operations tool | How easy will it be to distribute and run on the target platforms? |
| An addition to a large existing system | Does the new language's benefit justify maintaining another service? |
| Specialized computation or real-time work | Are the required libraries and latency guarantees available? |
What should you be able to explain now?
Go's value does not come from one feature alone. Understandable code, a short development cycle, language support for concurrency, and practical distribution can work together to help with particular tasks. When you can connect each benefit to a concrete requirement, you have moved from a promotional claim to an engineering decision.
In the next lesson, we will examine the structure of a first Go program. You do not need to memorize syntax yet. Work through the scenario below and try to explain your reasoning in the self-check questions.
- Simplicity affects the team's time.
Clear code makes onboarding, debugging, and later changes easier.
- Each mechanism has its own job.
Static typing checks compatibility, compilation prepares executable code, and the runtime helps manage memory and goroutines.
- Making progress together differs from running simultaneously.
Concurrency coordinates tasks; parallelism executes them at the same time. Starting another request while waiting for a network response is a useful way to remember the distinction.
- A language choice should follow a concrete requirement.
When recommending Go, identify two benefits and one limitation. Then check your decision with a small prototype and measurements.
Explain the team's language choice
A team of three is building a service that reads product prices from several stores. Most requests spend their time waiting for network responses. The service will run on a Linux server. The team is new to Go.
Write down two benefits and two risks of choosing Go. Then plan an experiment: what would you measure before deciding?
Compare your answer with an example approach
Go is a suitable candidate for coordinating independent network requests and simplifying distribution. However, the team's learning time and external API rate limits matter. Starting more goroutines does not remove those limits.
Use a small prototype to measure response latency, memory use, and failed requests under the same load. Set timeouts and limit simultaneous requests. Examine slow responses as well as averages.
Check your understanding
Choose an answer, then read the explanation. You can change your choice and try again.
Sources and further reading
This lesson is based on the topics in Matt Holiday's introductory Go Class slides. The practical scenario, comparisons, and self-check questions were written specifically for this lesson.