web-dev-qa-db-fra.com

Comment faire une ligne si autre déclaration?

Puis-je écrire une simple instruction if-else avec affectation de variable dans go (golang) comme je le ferais dans php (par exemple):

$var = ( $a > $b )? $a: $b;

actuellement, je dois utiliser les éléments suivants:

var c int
if a > b {
    c = a
} else {
    c = b
}

Désolé, je ne me souviens pas du nom si cette instruction de contrôle et je ne pouvais pas trouver les informations via la recherche sur le site et sur Google. : /

56
thoroc

Comme mentionné dans les commentaires, Go ne prend pas en charge les liners ternaires. La forme la plus courte à laquelle je puisse penser est la suivante:

var c int
if c = b; a > b {
    c = a
}
85
Not_a_Golfer

J'utilise souvent les éléments suivants:

c := b
if a > b {
    c = a
}

fondamentalement la même chose que @ Not_a_Golfer mais en utilisant type inference .

22
xoyuz

Comme les autres l’ont mentionné, Go ne prend pas en charge les one-liners ternaires. Cependant, j'ai écrit une fonction utilitaire qui pourrait vous aider à réaliser ce que vous voulez.

// IfThenElse evaluates a condition, if true returns the first parameter otherwise the second
func IfThenElse(condition bool, a interface{}, b interface{}) interface{} {
    if condition {
        return a
    }
    return b
}

Voici quelques cas de test pour montrer comment vous pouvez l'utiliser

func TestIfThenElse(t *testing.T) {
    assert.Equal(t, IfThenElse(1 == 1, "Yes", false), "Yes")
    assert.Equal(t, IfThenElse(1 != 1, nil, 1), 1)
    assert.Equal(t, IfThenElse(1 < 2, nil, "No"), nil)
}

Pour le plaisir, j'ai écrit des fonctions utilitaires plus utiles telles que:

IfThen(1 == 1, "Yes") // "Yes"
IfThen(1 != 1, "Woo") // nil
IfThen(1 < 2, "Less") // "Less"

IfThenElse(1 == 1, "Yes", false) // "Yes"
IfThenElse(1 != 1, nil, 1)       // 1
IfThenElse(1 < 2, nil, "No")     // nil

DefaultIfNil(nil, nil)  // nil
DefaultIfNil(nil, "")   // ""
DefaultIfNil("A", "B")  // "A"
DefaultIfNil(true, "B") // true
DefaultIfNil(1, false)  // 1

FirstNonNil(nil, nil)                // nil
FirstNonNil(nil, "")                 // ""
FirstNonNil("A", "B")                // "A"
FirstNonNil(true, "B")               // true
FirstNonNil(1, false)                // 1
FirstNonNil(nil, nil, nil, 10)       // 10
FirstNonNil(nil, nil, nil, nil, nil) // nil
FirstNonNil()                        // nil

Si vous souhaitez utiliser l'un de ces éléments, vous pouvez les trouver ici https://github.com/shomali11/util

15
Raed Shomali

Merci d'avoir indiqué la bonne réponse. 

Je viens de vérifier le Golang FAQ (duh) et il est clairement indiqué que ceci n'est pas disponible dans la langue:

Est-ce que Go a le?: Opérateur?

Il n'y a pas de forme ternaire dans Go. Vous pouvez utiliser les éléments suivants pour obtenir le même résultat:

if expr {
    n = trueVal
} else {
    n = falseVal
}

informations supplémentaires trouvées susceptibles d'intéresser le sujet:

9
thoroc

Une façon possible de faire cela en une seule ligne en utilisant une carte est simple, je vérifie si a > b si c'est true J'attribue c à a sinon b

c := map[bool]int{true: a, false: b}[a > b]

Cependant, cela semble étonnant, mais dans certains cas, cela pourrait ne pas être la solution parfaite en raison de l'ordre d'évaluation. Par exemple, si je vérifie si un objet n'est pas nil en obtenir une propriété, examinez l'extrait de code suivant qui va panic dans le cas de myObj equals nil

type MyStruct struct {
   field1 string
   field2 string 
}

var myObj *MyStruct
myObj = nil 

myField := map[bool]string{true: myObj.field1, false: "empty!"}[myObj != nil}

Parce que la carte sera créée et construite avant d'évaluer la condition, donc dans le cas de myObj = nil, cela paniquera tout simplement. 

Sans oublier de mentionner que vous pouvez toujours faire les conditions en une seule ligne, vérifiez les points suivants: 

var c int
...
if a > b { c = a } else { c = b}
2
msoliman

Parfois, j'essaie d'utiliser une fonction anonyme pour parvenir à définir et à affecter la même ligne. comme ci-dessous: 

a, b = 4, 8

c := func() int {
    if a >b {
      return a
    } 
    return b
  } ()

https://play.golang.org/p/rMjqytMYeQ0

1
Ron

Utiliser la fonction lambda au lieu de l'opérateur ternaire

Exemple 1

pour donner le max int

package main

func main() {

    println( func(a,b int) int {if a>b {return a} else {return b} }(1,2) )
}

Exemple 2

Supposons que vous disposiez de cette fonction must(err error) pour gérer les erreurs et que vous souhaitiez l'utiliser lorsqu'une condition n'est pas remplie. (profitez à https://play.golang.com/p/COXyo0qIslP )

package main

import (
    "errors"
    "log"
    "os"
)

// must is a little helper to handle errors. If passed error != nil, it simply panics.
func must(err error) {
    if err != nil {
        log.Println(err)
        panic(err)
    }
}

func main() {

    tmpDir := os.TempDir()
    // Make sure os.TempDir didn't return empty string
    // reusing my favourite `must` helper
    // Isn't that kinda creepy now though?
    must(func() error {
        var err error
        if len(tmpDir) > 0 {
            err = nil
        } else {
            err = errors.New("os.TempDir is empty")
        }
        return err
    }()) // Don't forget that empty parentheses to invoke the lambda.
    println("We happy with", tmpDir)
}
0
Alice Vixie

Une construction très similaire est disponible dans la langue

**if <statement>; <evaluation> {
   [statements ...]
} else {
   [statements ...]
}*

*

c'est à dire.

if path,err := os.Executable(); err != nil {
   log.Println(err)
} else {
   log.Println(path)
}
0
user2680100

Vous pouvez utiliser une fermeture pour cela:

func doif(b bool, f1, f2 func()) {
    switch{
    case b:
        f1()
    case !b:   
        f2()
    }
}

func dothis() { fmt.Println("Condition is true") }

func dothat() { fmt.Println("Condition is false") }

func main () {
    condition := true
    doif(condition, func() { dothis() }, func() { dothat() })
}

Le seul reproche que j’ai avec la syntaxe de fermeture dans Go est qu’il n’ya pas d’alias pour la fonction de retour zéro paramètre zéro par défaut, alors ce serait beaucoup plus agréable (pensez à la façon dont vous déclarez des littéraux de carte, de tableau et de slice avec juste un nom de type).

Ou même la version plus courte, comme un commentateur vient de le suggérer:

func doif(b bool, f1, f2 func()) {
    switch{
    case b:
        f1()
    case !b:   
        f2()
    }
}

func dothis() { fmt.Println("Condition is true") }

func dothat() { fmt.Println("Condition is false") }

func main () {
    condition := true
    doif(condition, dothis, dothat)
}

Vous auriez toujours besoin d'utiliser une fermeture si vous deviez donner des paramètres aux fonctions. Cela pourrait être évité dans le cas de méthodes de passage plutôt que de fonctions, je pense, où les paramètres sont la structure associée aux méthodes.

0
Louki Sumirniy