Golang 多个 goroutine 通过引用共享同一个变量

Golang multiple goroutine sharing same variable by reference

我正在尝试 运行 多个 goroutines 修改通过引用传递的相同变量。

但我确信我实现它的方式在功能上是不正确的。尽管它似乎在我的测试中有效,但我有一种感觉,如果第二个 goroutine 比第一个 goroutine 花费更长的时间 运行,那么当第一个 goroutine 完成时,这种模式会结束父函数。

我想要你的input/suggestions/advice.

package auth

import (
    "regexp"

    zxcvbn "github.com/nbutton23/zxcvbn-go"
    "golang.org/x/net/context"
)

type AuthService struct{}

func NewAuthService() *AuthService {
    return &AuthService{}
}

func (this *AuthService) ValidateCredentials(ctx context.Context, req *ValidateCredentialsRequest) (*ValidateCredentialsResponse, error) {
    c := make(chan *ValidateCredentialsResponse)

    go validatePassword(req.GetPassword(), c)
    go validateUsername(req.GetUsername(), c)

    c <- &ValidateCredentialsResponse{IsValid: true}

    return <-c, nil
}

func validateUsername(email string, c chan *ValidateCredentialsResponse) {
    for {
        res := <-c

        if email == "" {
            res.IsValid = false
            res.Username = "Please provide your email address."
        } else if len(email) > 128 {
            res.IsValid = false
            res.Username = "Email address can not exceed 128 characters."
        } else if !regexp.MustCompile(`.+@.+`).MatchString(email) {
            res.IsValid = false
            res.Username = "Please enter a valid email address."
        }

        c <- res
    }
}

func validatePassword(password string, c chan *ValidateCredentialsResponse) {
    for {
        res := <-c

        if password == "" {
            res.IsValid = false
            res.Password = "Please provide your password."
        } else {
            quality := zxcvbn.PasswordStrength(password, []string{})
            if quality.Score < 3 {
                res.IsValid = false
                res.Password = "Your password is weak."
            }
        }

        c <- res
    }
}

您确定需要 goroutines 来执行简单的验证吗? 无论如何,您编写的代码使用了 goroutine,但它们不是 运行 并行的。

您的代码中发生了什么: 您创建 non-buffered 通道并将 CredentialResponse 变量放入其中。 然后一个 goroutine(两个中的任何一个)从通道读取变量,执行一些操作,然后将变量放回通道。 当第一个 goroutine 正在执行一些操作时,第二个 goroutine 只是在等待来自通道的值。

所以你的代码使用了goroutines,但是很难称之为并行

如果您需要一些繁重的操作来验证数据,您可能希望使用 goroutines:io ops,或 CPU,但在 CPU 的情况下,您需要指定 GOMAXPROCS>1 以获得一些性能收获。

如果我想使用 goroutines 进行验证,我会这样写:

func validateCredentials(req *ValidateCredentialsRequest){
    ch := make(chan bool, 2)
    go func(name string){
    // ... validation code
        ch <- true // or false

    }(req.GetUsername())

    go func(pwd string){
    // ... validation code
        ch <- true // or false
    }(req.GetPassword())

    valid := true
    for i := 0; i < 2; i++ {
        v := <- result
        valid = valid && v
    }

    // ...
}