Goroutines Basics
Part of the Object Oriented Programming section of Coddy's GO journey — lesson 59 of 107.
A goroutine is a lightweight thread of execution managed by the Go runtime. Unlike traditional threads that consume significant memory, goroutines start with just a few kilobytes of stack space, allowing you to run thousands of them concurrently.
To start a goroutine, simply place the go keyword before a function call:
func sayHello(name string) {
fmt.Println("Hello,", name)
}
func main() {
go sayHello("Alice") // runs concurrently
go sayHello("Bob") // runs concurrently
time.Sleep(100 * time.Millisecond)
fmt.Println("Done")
}When go sayHello("Alice") executes, it doesn't wait for sayHello to finish. Instead, it immediately continues to the next line while sayHello runs in the background. This is why we need time.Sleep—without it, main would exit before the goroutines complete.
You can also launch goroutines with anonymous functions:
go func(msg string) {
fmt.Println(msg)
}("Hello from goroutine")The main function itself runs in a goroutine. When it returns, all other goroutines are terminated immediately—they don't get a chance to finish. Using time.Sleep is a temporary solution; in the upcoming lessons, you'll learn proper synchronization techniques with channels and wait groups.
Challenge
EasyLet's build a task runner that executes multiple tasks concurrently using goroutines. You'll create a simple system where tasks run in the background while the main program continues, demonstrating how goroutines enable concurrent execution.
You'll organize your code across two files:
tasks.go: Define your task execution logic.Create a
Taskstruct withName(string) andDuration(int, representing milliseconds) fields.Implement a method
Run()onTaskthat simulates work by sleeping for the task's duration, then prints:Task [Name] completedCreate a function
RunAllTasks(tasks []Task)that launches each task'sRun()method as a goroutine. After launching all goroutines, it should sleep for 500 milliseconds to allow them to complete, then print:All tasks launchedmain.go: Read task information and orchestrate the concurrent execution.Read the number of tasks, then read each task's name and duration. Create the tasks and pass them to
RunAllTasks. After it returns, print:Main function done
The following inputs will be provided:
- Line 1: Number of tasks (integer)
- Following lines: For each task, two lines - the task name, then its duration in milliseconds
For example, given:
3
Download
100
Process
50
Upload
75Your output should show tasks completing (order may vary due to concurrency), followed by the completion messages:
Task Process completed
Task Upload completed
Task Download completed
All tasks launched
Main function doneNote: Since goroutines run concurrently, tasks with shorter durations typically finish first. The task completion order depends on their durations - shorter tasks complete before longer ones.
Use time.Sleep with time.Duration and time.Millisecond for the delays. Remember that without the sleep in RunAllTasks, the function would return before goroutines finish their work.
Cheat sheet
A goroutine is a lightweight thread of execution managed by the Go runtime. Goroutines start with just a few kilobytes of stack space, allowing you to run thousands of them concurrently.
To start a goroutine, place the go keyword before a function call:
func sayHello(name string) {
fmt.Println("Hello,", name)
}
func main() {
go sayHello("Alice") // runs concurrently
go sayHello("Bob") // runs concurrently
time.Sleep(100 * time.Millisecond)
fmt.Println("Done")
}When go sayHello("Alice") executes, it doesn't wait for sayHello to finish. Instead, it immediately continues to the next line while sayHello runs in the background.
You can launch goroutines with anonymous functions:
go func(msg string) {
fmt.Println(msg)
}("Hello from goroutine")The main function itself runs in a goroutine. When it returns, all other goroutines are terminated immediately. Use time.Sleep to allow goroutines to complete before the main function exits.
Try it yourself
package main
import (
"fmt"
)
func main() {
// Read the number of tasks
var numTasks int
fmt.Scanln(&numTasks)
// TODO: Create a slice to hold the tasks
// TODO: Read each task's name and duration
// For each task:
// - Read the task name
// - Read the duration (as integer)
// - Create a Task and append to your slice
// TODO: Call RunAllTasks with your tasks slice
// TODO: Print "Main function done"
}
This lesson includes a short quiz. Start the lesson to answer it and track your progress.
All lessons in Object Oriented Programming
1Fundamentals of Go OOP
External FilesGo Workspace & ModulesPackages & ImportsExported vs Unexported NamesIntroduction to OOP in GoStructs as ClassesDefining Methods on StructsPointer vs Value ReceiversStruct InitializationConstructor FunctionsRecap - Simple Calculator4Interfaces
Introduction to InterfacesImplicit ImplementationInterface as ContractEmpty Interface (any)Type AssertionType SwitchInterface CompositionStringer & Error InterfacesRecap - Shape Calculator7Encapsulation
Exported vs Unexported FieldsPackage-Level EncapsulationGetter & Setter MethodsInformation Hiding in GoRecap - Student Records10Generics (Go 1.18+)
Introduction to GenericsType ParametersType ConstraintsGeneric StructsGeneric Methods WorkaroundRecap - Generic Collection2Types & Structs Deep Dive
Basic & Composite TypesCustom Type DefinitionsStruct TagsAnonymous StructsNested StructsZero Values & DefaultsRecap - Contact Book5Composition Over Inheritance
Why Go Has No InheritanceStruct Embedding BasicsMethod PromotionEmbedding Multiple StructsEmbedding vs AggregationShadowing Embedded MethodsRecap - Employee Hierarchy8Error Handling & OOP
The error InterfaceCustom Error TypesError Wrapping (fmt.Errorf)Sentinel Errorserrors.Is() and errors.As()Panic, Defer, and RecoverRecap - File Parser3Pointers & Memory
Pointer Basics in GoPointers to StructsPass by Value vs ReferenceThe new() FunctionGarbage Collection in GoRecap - Linked List Builder6Polymorphism in Go
Polymorphism via InterfacesDuck Typing in GoInterface Satisfaction RulesPolymorphic CollectionsDependency InjectionRecap - Payment Processor9Concurrency & OOP
Goroutines BasicsChannels & CommunicationBuffered vs Unbuffered ChanSelect Statementsync.Mutex & sync.RWMutexsync.WaitGroupThread-Safe Struct DesignRecap - Worker Pool