Goroutines are lightweight units of execution managed by the Go runtime scheduler to run functions concurrently.
In general, program execution can be divided into two types of routines:
Main Routine: The first goroutine started by a Go program. It executes the main() function in the main package and defines the lifetime of the program. When the main routine finishes, the program exits immediately, even if other goroutines are still running.
Child Routine: Any goroutine started from another routine using the go keyword. It runs concurrently with the parent routine and performs work independently. It does not block the parent unless synchronization is explicitly implemented. It completes when its function returns or when the program terminates.
func main() { go expensiveFunc("Hello") // Run expensiveFunc concurrently (don't wait for it) fmt.Println("Main") time.Sleep(1700 * time.Millisecond)}func expensiveFunc(text string) { for i := 0; i < 4; i++ { time.Sleep(500 * time.Millisecond) fmt.Println(text, i) }}// Main// Hello 0// Hello 1// Hello 2
The time.Sleep in the main function is used only to give the goroutine enough time to run before the main routine exits. Without it, the program would terminate as soon as the main routine completes.
The output shows only 3 iterations even though the loop is set for 4 iterations. This is because time.Sleep of 1700 ms is less than the 4 * 500 ms required for all iterations of expensiveFunc. Meaning only the first 3 iterations had enough time to complete before the program exited.
In Go, a Mutex (Mutual Exclusion) from the sync is a locking mechanism that allows only one goroutine at a time to read or modify shared data, forcing others to wait until it is free. This prevents race conditions and keeps the data consistent.
How it works:
Lock() attempts to acquire the mutex.
If the mutex is free, the goroutine acquires it and continues.
If the mutex is locked, the goroutine is blocked until it becomes available.
Unlock() releases the mutex and allows one waiting goroutine to acquire it.
Only one goroutine can hold the lock at a time. The mutex is not tied to any specific goroutine. Any goroutine can compete to acquire it when it becomes available.
Calling Unlock() on an unlocked mutex causes a panic.