Consider the following code snippet, which employs a channel of type struct{} to facilitate communication between goroutines:
package main import "fmt" var battle = make(chan string) func warrior(name string, done chan struct{}) { select { case opponent := <-battle: fmt.Printf("%s beat %s\n", name, opponent) case battle <- name: // I lost :-( } done <- struct{}{} } func main() { done := make(chan struct{}) langs := []string{"Go", "C", "C++", "Java", "Perl", "Python"} for _, l := range langs { go warrior(l, done) } for _ = range langs { <-done } }
[Question 1]
The line done <- struct{}{}, which sends an empty struct to the done channel, has sparked confusion. While an ordinary struct can be declared with struct { /* fields */ }, an empty struct is denoted by struct{}{}, which prompts a few questions:
An empty struct is a struct that doesn't have any fields. It's also known as an anonymous struct. The purpose of an empty struct is to provide a way to create a type that has no fields, which can be useful for various reasons, such as:
In our code, we use an anonymous struct to signal that a goroutine has finished its work. Using an empty struct for this purpose is advantageous because it has a size of 0, minimizing memory footprint.
[Question 2]
The line for _ = range langs { <-done } is responsible for receiving and discarding values from the done channel. This line is necessary for the following reasons:
By using a channel of type struct{} and an empty struct as a signaling mechanism, we can achieve efficient communication between goroutines with minimal overhead.
The above is the detailed content of Anonymous Structs vs. Empty Structs in Go: Why Use `struct{}` for Goroutine Synchronization?. For more information, please follow other related articles on the PHP Chinese website!