diff --git a/concurrency/goroutine_leak/main.go b/concurrency/goroutine_leak/main.go new file mode 100644 index 0000000..c262739 --- /dev/null +++ b/concurrency/goroutine_leak/main.go @@ -0,0 +1,49 @@ +package main + +import "fmt" + +// The goroutine has a few paths to termination: +// • When it has completed its work. +// • When it cannot continue its work due to an unrecoverable error. +// • When it’s told to stop working + +/** +We get the first two paths for free—these paths are your algorithm—but what about +work cancellation? This turns out to be the most important bit because of the net‐ +work effect: if you’ve begun a goroutine, it’s most likely cooperating with several other +goroutines in some sort of organized fashion. +**/ + +func main() { + +} + +// Here we see that the main goroutine passes a nil channel into doWork. Therefore, the +// strings channel will never actually gets any strings written onto it, and the goroutine +// containing doWork will remain in memory for the lifetime of this process (we would +// even deadlock if we joined the goroutine within doWork and the main goroutine). +// In this example, the lifetime of the process is very short, but in a real program, gorou‐ +// tines could easily be started at the beginning of a long-lived program. In the worst +// case, the main goroutine could continue to spin up goroutines throughout its life, +// causing creep in memory utilization. +func resourceLeak() { + doWork := func(strings <-chan string) <-chan interface{} { + completed := make(chan interface{}) + go func() { + defer fmt.Println("doWork exited.") + defer close(completed) + for s := range strings { + // Do something interesting + fmt.Println(s) + } + }() + return completed + } + doWork(nil) + // Perhaps more work is done here + fmt.Println("Done.") +} + +func cancellationSignal() { + +} diff --git a/for-range-semantics/main.go b/for-range-semantics/main.go new file mode 100644 index 0000000..8e389e1 --- /dev/null +++ b/for-range-semantics/main.go @@ -0,0 +1,21 @@ +package main + +import "fmt" + +type user struct { + name string + email string +} + +func main() { + users := []user{ + {"Bill", "bill@email.com"}, + {"Lisa", "lisa@email.com"}, + {"Nancy", "nancy@email.com"}, + {"Paul", "paul@email.com"}, + } + + for i, u := range users { + fmt.Println(i, u) + } +}