去++运算符需要互斥吗?

Does go ++ Operator need mutex? It seems that when not using mutex i am losing some data , but by logic ++ just add +1 value to the current value , so even if the order is incorrect still a total of 1000 run should happen no? Example:

package main

import (
    "fmt"
    "sync"
)

func main() {
    var wg sync.WaitGroup
    i := 0
    for r := 0; r < 1000; r++ {
        wg.Add(1)
        go func() {
            i++
            fmt.Println(i)
            wg.Done()
        }()
    }
    wg.Wait()
    fmt.Printf("%d Done", i)
}

just add +1 value to the current value

No, it's not "just add". It's

  1. Read current value
  2. Compute new value (based on what was read) and write it

See how this can break with multiple concurrent actors?

If you want atomic increments, check out sync/atomic. Examples: https://gobyexample.com/atomic-counters

To "just add 1 to the current value" the computer needs to read the current value, add 1, and write the new value back. Clearly ordering does matter; the standard example is:

Thread A     Thread B
Read: 5
             Read: 5
+1 = 6
             +1 = 6
Write: 6
             Write: 6

The value started at 5, two threads of execution each added one, and the result is 6 (when it should be 7), because B's read occurred before A's write.

But there's a more important misconception at play here: many people think that in the case of a race, the code will either read the old value, or it will read the new value. This is not guaranteed. It might be what happens most of the time. It might be what happens all the time on your computer, with the current version of the compiler, etc. But actually it's possible for code that accesses data in an unsafe/racy manner to produce any result, even complete garbage. There's no guarantee that the value you read from a variable corresponds to any value it has ever had, if you cause a race.