2017-02-05 24 views
-2

Я пытаюсь запустить несколько goroutines, которые изменяют ту же переменную, переданную по ссылке.Golang multiple goroutine разделяет одну и ту же переменную по ссылке

Но я уверен, что способ, который я реализовал, является функционально неправильным. Несмотря на то, что он, кажется, работает в моих тестах, у меня такое чувство, что этот шаблон завершит родительскую функцию, когда первый goroutine завершится, если второй goroutine займет значительно больше времени, чем первый.

Я хотел бы ваш вход/предложения/советы.

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(`[email protected]+`).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 
    } 
} 
+0

идиоматических способ писать код, указанный выше, чтобы написать validatePassword и validateUsername как простые функции, которые возвращают значения , Горутины здесь не дают никакой ценности. –

ответ

2

Вы уверены, что вам нужны goroutines для выполнения простых проверок? В любом случае код, который вы написали, использует goroutines, но они не работают параллельно.

Что происходит в вашем коде: вы создаете небуферизованный канал и вставляете в него переменную CredentialResponse. Затем один goroutine (любой из двух) считывает переменную из канала, выполняет некоторые действия и помещает переменную обратно в канал. В то время как первый goroutine делал некоторые действия, второй из них просто ждал значения из канала.

Таким образом, ваш код использует goroutines, но его вряд ли можно назвать параллельным.

Возможно, вы захотите использовать goroutines, если вам нужны тяжелые операции для проверки данных: io ops или 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 
    } 

    // ... 
} 
+2

JFTR, в наши дни «GOMAXPROCS» равно количеству ядер («виртуальные процессоры», о которых сообщает ОС) при запуске программы. Реальная проблема заключается в том, является ли проверка имени пользователя и пароля ресурсом, потребляющим ресурсы, чтобы перевесить затраты на создание goroutines и синхронизировать их? Да, создание goroutines грязно-дешево по сравнению с потоками уровня ОС, но эта стоимость не равна нулю. – kostix

 Смежные вопросы

  • Нет связанных вопросов^_^