Quelle méthode est la meilleure (plus idomatique) pour tester des chaînes non vides (dans Go)?
if len(mystring) > 0 { }
Ou:
if mystring != "" { }
Ou autre chose?
Les deux styles sont utilisés dans les bibliothèques standard de Go.
if len(s) > 0 { ... }
peut être trouvé dans le strconv
package: http://golang.org/src/pkg/strconv/atoi.go
if s != "" { ... }
peut être trouvé dans le encoding/json
package: http://golang.org/src/pkg/encoding/json/encode.go
Les deux sont idiomatiques et assez clairs. C'est plus une question de goût personnel et de clarté.
Russ Cox écrit dans un fil de noix de golang :
Celui qui rend le code clair.
Si je suis sur le point de regarder l'élément x, j'écris généralement
len (s)> x, même pour x == 0, mais si je me soucie de
"est-ce cette chaîne spécifique", j'ai tendance à écrire s == "".Il est raisonnable de supposer qu'un compilateur mature compilera
len (s) == 0 et s == "" dans le même code efficace.
...Rendez le code clair.
Comme indiqué dans la réponse de Timmmm , le compilateur Go génère du code identique dans les deux cas.
if mystring != "" { }
la meilleure façon, préférée et idiomatique AUJOURD'HUI. La raison pour laquelle la bibliothèque standard contient autre chose est qu'elle a été écrite avant 2010 lorsque l'len(mystring) == 0
optimisation était logique.len
pour vérifier les chaînes vides / non vides. Comme cet engagement de Brad Fitzpatrick. J'ai bien peur que ce soit encore une question de goût et de clarté;)len(v) > 0
dans h2_bundle.go (ligne 2702). Il ne s'affiche pas automatiquement car il est généré à partir de golang.org/x/net/http2, je crois.Cela semble être une microoptimisation prématurée. Le compilateur est libre de produire le même code pour les deux cas ou au moins pour ces deux
et
parce que la sémantique est clairement égale.
la source
La vérification de la longueur est une bonne réponse, mais vous pouvez également prendre en compte une chaîne "vide" qui n'est également qu'un espace blanc. Pas "techniquement" vide, mais si vous voulez vérifier:
la source
TrimSpace
va allouer et copier une nouvelle chaîne à partir de la chaîne d'origine, donc cette approche introduira des inefficacités à grande échelle.s
est de type chaîne,s[0:i]
retourne une nouvelle copie. Les chaînes sont immuables dans Go, faut-il donc en créer une copie ici?strings.TrimSpace( s )
n'entraînera pas une nouvelle allocation de chaîne et une nouvelle copie de caractères si la chaîne n'a pas besoin d'être coupée, mais si la chaîne a besoin d'être coupée, la copie supplémentaire (sans les espaces) sera invoquée.gocritic
linter suggère d'utiliser à lastrings.TrimSpace(str) == ""
place du contrôle de longueur.En supposant que les espaces vides et tous les espaces blancs de début et de fin doivent être supprimés:
Car :
len("") // is 0
len(" ") // one empty space is 1
len(" ") // two empty spaces is 2
la source
< 1
+1À partir de maintenant, le compilateur Go génère du code identique dans les deux cas, c'est donc une question de goût. GCCGo génère un code différent, mais presque personne ne l'utilise, donc je ne m'inquiéterais pas de cela.
https://godbolt.org/z/fib1x1
la source
Il serait plus propre et moins sujet aux erreurs d'utiliser une fonction comme celle ci-dessous:
la source
Juste pour ajouter plus de commentaires
Principalement sur la façon de faire des tests de performances.
J'ai fait des tests avec le code suivant:
Et les résultats ont été:
En effet, les variantes n'atteignent généralement pas le temps le plus rapide et il n'y a qu'une différence minimale (environ 0,01 ns / op) entre la vitesse de pointe des variantes.
Et si je regarde le journal complet, la différence entre les essais est supérieure à la différence entre les fonctions de référence.
De plus, il ne semble pas y avoir de différence mesurable entre BenchmarkStringCheckEq et BenchmarkStringCheckNe ou BenchmarkStringCheckLen et BenchmarkStringCheckLenGt même si ces dernières variantes doivent augmenter c 6 fois au lieu de 2 fois.
Vous pouvez essayer d'obtenir une certaine confiance sur des performances égales en ajoutant des tests avec un test modifié ou une boucle interne. C'est plus rapide:
Ce n'est pas plus rapide:
Les deux variantes sont généralement plus rapides ou plus lentes que la différence entre les tests principaux.
Il serait également bon de générer des chaînes de test (ss) en utilisant un générateur de chaînes avec une distribution appropriée. Et ont également des longueurs variables.
Je n'ai donc aucune confiance en la différence de performances entre les principales méthodes pour tester une chaîne vide en cours.
Et je peux affirmer avec une certaine confiance, il est plus rapide de ne pas tester la chaîne vide du tout que de tester la chaîne vide. Et il est également plus rapide de tester une chaîne vide que de tester 1 chaîne de caractères (variante de préfixe).
la source
Selon les directives officielles et du point de vue des performances, ils semblent équivalents ( réponse ANisus ), le s! = "" Serait préférable en raison d'un avantage syntaxique. s! = "" échouera au moment de la compilation si la variable n'est pas une chaîne, tandis que len (s) == 0 passera pour plusieurs autres types de données.
la source
len()
suffit de ce petit peu de travail supplémentaire. TOUTEFOIS, une chose que nous avions l'habitude de faire en C était de convertir le côté gauche en aconst
ou de mettre la chaîne statique du côté gauche de l'opérateur pour empêcher s == "" de devenir s = "" ce qui dans la syntaxe C est acceptable. .. et probablement golang aussi. (voir l'extension si)Ce serait plus performant que de rogner la chaîne entière, car il vous suffit de vérifier au moins un seul caractère non espace existant
la source
Je pense que la meilleure façon est de comparer avec une chaîne vide
BenchmarkStringCheck1 vérifie avec une chaîne vide
BenchmarkStringCheck2 vérifie avec len zéro
Je vérifie avec la vérification de chaîne vide et non vide. Vous pouvez voir que la vérification avec une chaîne vide est plus rapide.
Code
la source