web-dev-qa-db-fra.com

Dans Go, est-il judicieux d'écrire du code non bloquant?

venant du point de vue node.js, où tout le code est non bloquant.

Dans Go, le non-blocage est facilement réalisé en utilisant des canaux.

si l'on écrivait un serveur de type node.js en cours, est-il judicieux de le rendre non bloquant? par exemple, le fait d'avoir une fonction de connexion à la base de données renvoie un canal, par opposition au blocage en attendant que la connexion se produise.

cela me semble la bonne approche

mais ...

39
cc young

Le blocage et le non-blocage ne concernent pas vraiment les performances, ils concernent une interface. Si vous avez un seul thread d'exécution, un appel de blocage empêche votre programme d'effectuer un travail utile pendant qu'il attend. Mais si vous avez plusieurs threads d'exécution, un appel de blocage n'a pas vraiment d'importance car vous pouvez simplement laisser ce thread bloqué et effectuer un travail utile dans un autre.

Dans Go, un goroutine est remplacé par un autre lorsqu'il se bloque sur les E/S. Le runtime Go utilise des appels système d'E/S non bloquants pour éviter que le système d'exploitation ne bloque le thread afin qu'un autre goroutine puisse être exécuté dessus pendant que le premier attend ses E/S.

Les goroutines sont vraiment bon marché, il n'est donc pas nécessaire d'écrire du code de style non bloquant.

66
Jessta

Écrire des fonctions de blocage. La langue vous permet de transformer facilement un appel synchrone en appel asynchrone.

Si vous souhaitez appeler une fonction de manière asynchrone, utilisez une instruction go. Quelque chose comme ça:

c := make(chan bool)
go func() {
    blockingFunction()
    c <- true
}()

// do some other stuff here while the blocking function runs

// wait for the blocking function to finish if it hasn't already
<-c
26
Evan Shaw

Dans Go, les appels système sont implémentés de manière non bloquante en utilisant le mécanisme sous-jacent le plus efficace pris en charge par le système d'exploitation (par exemple epoll). Si vous n'avez pas d'autre code à exécuter pendant que vous attendez le résultat d'un appel, il bloque le thread (faute d'une meilleure chose à faire), mais si vous avez des goroutines alternatives actives, alors elles s'exécuteront à la place.

Les rappels (comme vous en avez l'habitude dans js) permettent essentiellement la même mécanique sous-jacente, mais avec sans doute plus de gymnastique mentale nécessaire au programmeur.

Dans Go, votre code à exécuter après un appel de fonction est spécifié immédiatement après l'appel de fonction plutôt que défini comme rappel. Le code que vous souhaitez exécuter parallèlement à un chemin d'exécution doit être encapsulé dans un goroutine, avec une communication via des canaux.

19
tylerl

Pour les applications de type serveur Web typiques, je recommanderais de ne pas rendre tout asynchrone. Il y a quelques raisons.

  • Il est plus facile de raisonner sur le code de blocage série que le code asynchrone (plus facile à voir les bogues)

  • la gestion des erreurs de golang est basée sur defer (), panic () et recover (), qui ne vous donnera probablement pas ce que vous voulez avec du code 100% asynchrone

  • Les goroutines peuvent fuir si vous ne faites pas attention [une discussion] . Plus vous avez de comportement asynchrone, plus il devient difficile de détecter ces types de problèmes et plus ils sont susceptibles de se manifester.

Une stratégie consiste à concentrer l'asynchonicité à un niveau élevé et à laisser tout le reste bloquant. Vous pouvez donc avoir un blob "gestionnaire de base de données" qui est logiquement distinct du blob "gestionnaire de requêtes". Ils fonctionnent tous deux dans des goroutines séparées et communiquent à l'aide de canaux. Mais dans le "gestionnaire de base de données", les appels pour établir une connexion à la base de données et exécuter chaque requête sont bloquants.

Vous n'avez pas à choisir 100% asynchrone ou 0% asynchrone.

11
Nathan Whitehead

Les interfaces bloquantes sont toujours plus simples et meilleures que les interfaces non bloquantes. La beauté de Go est qu'il vous permet d'écrire du code simultané (et parallèle) dans un style de blocage simple et facile à raisonner.

La mode de programmation non bloquante est entièrement due à des déficiences dans les langues que les gens utilisent (spécialement JavaScript), pas parce que la programmation non bloquante est intrinsèquement meilleure.

6
uriel