Go Can';我不明白为什么这个循环是一场数据竞赛

Go Can';我不明白为什么这个循环是一场数据竞赛,go,Go,我有一个循环,它显然导致了一个数据竞争,在这个函数的底部附近,我将把它标记为: func (p *PartialParty) SendReadyCheck(party PartialParty) { msg, err := json.Marshal(&ReadyCheckMsg{"ReadyCheck", ""}) if err != nil { log.Println(err) } for _, member := range part

我有一个循环,它显然导致了一个数据竞争,在这个函数的底部附近,我将把它标记为:

func (p *PartialParty) SendReadyCheck(party PartialParty) {
    msg, err := json.Marshal(&ReadyCheckMsg{"ReadyCheck", ""})
    if err != nil {
        log.Println(err)
    }

    for _, member := range party.Members {
        member.Conn.send <- msg
    }

    counter := 0
    loopBreaker := true
    for {
        select {
        case <-p.Accept:
            counter++
            resp, err := json.Marshal(&ReadyCheckMsg{"ReadyAccepted", ""})
            if err != nil {
                log.Println(err)
            }
            for _, member := range party.Members {
                member.Conn.send <- resp
            }
            if counter == 2 {
                // Create a new party with all members
                partyid := PartyID(feeds.NewUUID().String())
                db := common.Db()
                newParty := &Party{
                    Active:    true,
                    Members:   p.Members,
                    Broadcast: make(chan []byte),
                    PartyID:   partyid,
                }

                // Insert the new party into the database
                _, err := db.Exec("INSERT INTO party SET party_id = ?, active = ?", partyid.String(), true)
                if err != nil {
                    log.Println(err)
                }

                // Go through the members and update the database
                var wg sync.WaitGroup

                for _, member := range party.Members {
                    wg.Add(1)
                    m := member
                    go func() {
                        _, err := db.Exec("UPDATE party_members SET active = ? WHERE steamid = ?", false, m.SteamID)
                        if err != nil {
                            log.Println(err)
                        }
                        _, err = db.Exec("INSERT INTO party_members SET belongs_to =?, active = ?, steamid = ?", partyid.String(), true, m.SteamID)
                        if err != nil {
                            log.Println(err)
                        }
                        wg.Done()
                    }()
                }

                // Wait for all the database stuff to finish
                wg.Wait()
                PHub.AddNewParty(newParty)
                loopBreaker = false
                break
            }
        case conn := <-p.Decline:
            if conn.Ready {
                break
            }
            conn.Ready = false
            conn.InQueue = false
            conn.CurrentParty = ""
            resp, err := json.Marshal(&ReadyCheckMsg{"ReadyCheckDeclined", ""})
            if err != nil {
                log.Println(err)
            }
            p.Accepting = true
            identifier := conn.Identifier
            if _, ok := party.Members[identifier]; ok {
                delete(p.Members, identifier)
            }
            for _, m := range party.Members {
                member := m
                member.Conn.send <- resp
            }
            log.Println("Here")
            loopBreaker = false
            break
        case <-time.After(30 * time.Second):
            if counter == 2 {
                return
            }
            p.Accepting = true
            failedMsg, err := json.Marshal(&ReadyCheckMsg{"FailedToReady", ""})
            if err != nil {
                log.Println(err)
            }
            somebodyDeclinedMsg, err := json.Marshal(&ReadyCheckMsg{"ReadyCheckDeclined", ""})
            if err != nil {
                log.Println(err)
            }


    >>>>     for _, member := range party.Members { ***<<<< This Line***
                m := member
                if !m.Conn.Ready {
                    m.Conn.Ready = false
                    m.Conn.InQueue = false
                    m.Conn.CurrentParty = ""
                    m.Conn.send <- failedMsg
                } else {
                    m.Conn.Ready = false
                    m.Conn.send <- somebodyDeclinedMsg
                }
            }
            loopBreaker = false
            break
        }
        if !loopBreaker {
            break
        }
    }
}
现在,如果goroutine
SendReadyCheck
正在运行,就不可能添加新成员,因为它受到if语句的保护,该语句检查goroutine是否正在运行,所以我不确定他们为什么说他们正在相互比赛。如果能帮我清理一下,那就太好了。我试着在循环中设置一个变量,试图避开它,但它似乎并没有引起它

现在,如果goroutine SendReadyCheck正在运行,则无法添加NewMember``因为它受到检查goroutine是否正在运行的if语句的保护

您实际上并没有显示代码的这一部分,但这大概不是不可能的。如果SendReadyCheck在if测试之后但在AddNewMember进行修改之前开始运行该怎么办

// AddNewMember will add a new user to the party
func (p *PartyHub) AddNewMember(member *Member, partyid PartyID) {
    p.Lock()
    defer p.Unlock()
>>> p.PartialPartys[partyid].Members[member.Conn.Identifier] = member
}

type PartialParty struct {
    Accepting bool
    Members   map[Identifier]*Member
    Accept    chan *Connection
    Decline   chan *Connection
    PartyID   PartyID
    sync.Mutex
}