Urgent.News

600+ sources. One page. See who else covered it.

Editions โ–พ

Tech

Why Does Go Have Goroutines? Understanding Goโ€™s Lightweight Concurrency

When I started exploring Go, one feature immediately stood out: go doSomething () Just adding go before a function call can run it concurrently. That got me thinking: what exactly is a goroutine, and why does Go need it? So, I decided to learn the basics. Here's what I found. ๐Ÿ‘‡ First, what is concurrency? Imagine you have multiple tasks: Fetching data from an API Processing a file Handling userโ€ฆ

When I began delving into Go, one feature immediately caught my attention: the ability to run a function concurrently by simply prepending `go` before the function call. This triggered my curiosity about the underlying concept of a goroutine and the reason why Go necessitates such a construct. To learn the fundamentals, I embarked on a journey to understand the basics. Here's a summary of what I discovered.

First, let's define concurrency. Picture yourself juggling multiple tasks: fetching data from an API, processing a file, handling user requests, and writing data to a database. If your program executed these tasks sequentially, one task might spend a considerable amount of time waiting while the others are blocked. Concurrency allows a program to make progress on multiple tasks during overlapping time periods. This becomes particularly useful when programs must handle large volumes of work efficiently.

Moving on to the concept of a goroutine, a goroutine is essentially a function that runs concurrently alongside other goroutines. Creating a goroutine is surprisingly straightforward:

```go

package main

import "fmt"

func sayHello() {

fmt.Println("Hello from a goroutine!")

}

func main() {

go sayHello()

fmt.Println("Hello from main!")

}

```

The distinguishing factor here is the `go` keyword, which instructs Go to initiate `sayHello()` as a goroutine. However, there's a caveat: if you run the aforementioned example, you might not always observe `Hello from a goroutine!` appearing on the output. This is because the `main()` function finishes as soon as the program exits, potentially leaving the goroutine insufficient time to complete its execution. To ensure wait for goroutines, Go provides the `sync.WaitGroup` mechanism. Here's an example:

```go

package main

import (

"fmt"

"sync"

)

func main() {

var wg sync.WaitGroup

wg.Add(2)

go func() {

defer wg.Done()

fmt.Println("Task 1 completed")

}()

go func() {

defer wg.Done()

fmt.Println("Task 2 completed")

}()

wg.Wait()

fmt.Println("All tasks completed")

}

```

In this snippet, `wg.Add(2)` instructs the `WaitGroup` to anticipate completion of 2 tasks. Each function is started as a goroutine using the `go` keyword. The `defer wg.Done()` statement signals that a task has been completed. Lastly, `wg.Wait()` prevents the `main()` function from terminating until all tasks have been successfully completed.

Contrasting goroutines with traditional threads reveals the unique essence of Go. Unlike conventional threads managed directly by the operating system, goroutines are lightweight units of concurrent execution orchestrated by the Go runtime. This runtime efficiently schedules goroutines onto OS threads, enabling the handling of a vast number of goroutines without the overhead of manually creating and managing threads for each task.

This is one of the key reasons Go has gained popularity among developers working on systems and services requiring the capability to manage numerous concurrent operations.

Delving deeper into concurrency, it's essential to distinguish it from parallelism. Concurrency refers to structuring a program in a manner that multiple tasks can progress independently. Parallelism involves the actual simultaneous execution of multiple tasks, leveraging multiple processing resources. A program can be concurrent but not necessarily parallel, as tasks don't need to run at the exact same instant.

When combined with channels, goroutines attain enhanced functionality. Channels serve as conduits for communication and synchronization between goroutines, making the Go concurrency model more robust than merely executing everything concurrently.

Reflecting on my journey into Go, my primary takeaway is that goroutines simplify the concept of concurrency, yet the Go runtime undertakes substantial work behind the scenes to manage these concurrent tasks efficiently. Initiating a goroutine with `go doSomething()` merely scratches the surface, paving the way for further exploration into scheduling, synchronization, channels, race conditions, parallelism, and scalable systems.

My next step in understanding Go's concurrency model remains intriguing: should I venture into channels, interfaces, defer, or explore another aspect?

Written by urgent.news from Dev.to's reporting โ€” not their text. Machine-written โ€” may contain errors; check the original before relying on it.

Read the original at dev.to โ†’

More in Tech

Karachi Ki Raatein: A Love Letter to Midnight Street Food

This is a submission for Frontend Challenge - Comfort Food Edition, Perfect Landing What I Built Karachi Ki Raatein ("Karachi's Nights") โ€” a single-page love letter to the street food that keeps myโ€ฆ

  • Karachi Ki Raatein celebrates Karachi's midnight street food culture
  • Canvas particle system simulates steam dynamically reacting to cursor
  • Dark aesthetics with ember, turmeric colors and hand-lettered font

Overlaying a design on a live page: four things that bit me

I spent the last few weeks building a Chrome extension that puts a design frame on top of a running web page so you can see where the implementation drifted.

  • Fixed position overlays shift when scrolling
  • Overlay must be in document space, not fixed
  • Image dimensions are not accurate, calculate with scale factor

Your `if` statements are a database nobody can query

Somewhere in your codebase there is a line that looks like this: if ( user . plan === ' enterprise ' || user . tenantId === ' acme-corp ' ) { // ... } Nobody remembers who wrote the second half of that condition. It has been there for two years. It is almost certainly still load-bearing.

  • Rules scattered across codebase, not queryable
  • Lack of schema, querying, migrations, audit log
  • Moving rules to separate service introduces latency and kill switch issues

More from Saturday 15 August โ†’