Home > Backend Development > Golang > Why Does My Go Code Print 'Three' Three Times Instead of 'One,' 'Two,' and 'Three' in a Goroutine Data Race?

Why Does My Go Code Print 'Three' Three Times Instead of 'One,' 'Two,' and 'Three' in a Goroutine Data Race?

Linda Hamilton
Release: 2024-12-07 22:23:13
Original
926 people have browsed it

Why Does My Go Code Print

Understanding the Curious Behavior of Goroutines in a Data Race Scenario

In the provided Go code, we create a slice of struct fields called data containing names "one," "two," and "three." The code iterates through the slice, creating goroutines to print each field's name using the print method. However, contrary to expectations, the code repeatedly prints "three" three times, rather than the intended sequence of "one," "two," and "three."

Unveiling the Data Race

This curious behavior stems from a data race, which occurs when multiple goroutines access and potentially modify the same shared data concurrently. In this case, the issue arises from the implicit use of the address of the range variable v when creating the goroutines. When the loop variable v is changed in each iteration, the goroutines end up using its final value, resulting in the constant printing of "three."

Addressing the Data Race

To resolve this issue, we can adopt several approaches:

  • Creating a New Variable in Each Loop Iteration: Within the loop, we can declare a new variable with the same name as the range variable, effectively creating a new scope for the variable.

    for _, v := range data {
      v := v // Declare a new variable `v` within the loop scope.
      go v.print()
    }
    Copy after login
  • Using a Slice of Pointers: Instead of using a slice of struct fields, we can use a slice of pointers to the fields. This ensures that the goroutines receive pointers to individual field elements, preventing data race issues.

    data := []*field{ {"one"},{"two"},{"three"} }
    for _, v := range data {
      go v.print()
    }
    Copy after login
  • Passing the Address of the Slice Element: Another alternative is to pass the address of each element in the slice to the goroutine.

    for i := range data {
      v := &data[i] // Take the address of the slice element.
      go v.print()
    }
    Copy after login
  • Using Anonymous Functions and Passing Range Variables as Arguments: If the goroutine function is within an anonymous function, we can avoid the issue by passing the range variables as arguments to the function.

    for _, v := range data {
      go func(v field) { // Pass the range variable `v` as an argument.
          v.print()
      }(v)
    }
    Copy after login

These approaches ensure that the goroutines have their own copies of the data they need, eliminating the data race and producing the correct output of "one," "two," and "three" in any order.

The above is the detailed content of Why Does My Go Code Print 'Three' Three Times Instead of 'One,' 'Two,' and 'Three' in a Goroutine Data Race?. For more information, please follow other related articles on the PHP Chinese website!

source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Latest Articles by Author
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template