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
}
// ...
}
我正在尝试 运行 多个 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
}
// ...
}