Paramètres facultatifs?

Est-ce que Go peut avoir des parameters optionnels? Ou est-ce que je peux simplement définir deux fonctions avec le même nom et un nombre différent d’arguments?

Go n’a pas de parameters optionnels ni ne prend en charge la surcharge de méthodes :

L’envoi de la méthode est simplifié s’il n’est pas nécessaire de faire également la correspondance de type. L’expérience avec d’autres langues nous a montré qu’il était parfois utile d’avoir une variété de méthodes portant le même nom, mais des signatures différentes, mais que cela pouvait aussi être déroutant et fragile dans la pratique. La correspondance uniquement par nom et nécessitant une cohérence dans les types était une décision de simplification majeure dans le système de type Go.

Un moyen intéressant d’obtenir des parameters optionnels est d’utiliser des arguments variadiques. La fonction reçoit en réalité une tranche de n’importe quel type que vous spécifiez.

 func foo(params ...int) { fmt.Println(len(params)) } func main() { foo() foo(1) foo(1,2,3) } 

Vous pouvez utiliser une structure qui inclut les parameters:

 type Params struct { a, b, c int } func doIt(p Params) int { return pa + pb + pc } // you can call it without specifying all parameters doIt(Params{a: 1, c: 9}) 

Pour un nombre arbitraire, potentiellement grand nombre de parameters optionnels, un bon langage consiste à utiliser les options fonctionnelles .

Pour votre type Foobar , écrivez d’abord un seul constructeur:

 func NewFoobar(options ...func(*Foobar) error) (*Foobar, error){ fb := &Foobar{} // ... (write initializations with default values)... for _, op := range options{ err := op(fb) if err != nil { return nil, err } } return fb, nil } 

où chaque option est une fonction qui mute le Foobar. Ensuite, fournissez à votre utilisateur des moyens pratiques d’utiliser ou de créer des options standard, par exemple:

 func OptionReadonlyFlag(fb *Foobar) error { fb.mutable = false return nil } func OptionTemperature(t Celsius) func(*Foobar) error { return func(fb *Foobar) error { fb.temperature = t return nil } } 

Cour de récréation

Pour la concision, vous pouvez donner un nom au type des options ( Playground ):

 type OptionFoobar func(*Foobar) error 

Si vous avez besoin de parameters obligatoires, ajoutez-les en tant que premiers arguments du constructeur avant les options variadic.

Les principaux avantages de l’idiome d’ options fonctionnelles sont:

  • votre API peut évoluer au fil du temps sans casser le code existant, car la signature de la structure rest la même lorsque de nouvelles options sont nécessaires.
  • il permet au cas d’utilisation par défaut d’être le plus simple: pas d’arguments du tout!
  • il permet un contrôle précis de l’initialisation des valeurs complexes.

Cette technique a été inventée par Rob Pike et également démontrée par Dave Cheney .

Ni les parameters facultatifs ni la surcharge des fonctions ne sont pris en charge dans Go. Go prend en charge un nombre variable de parameters: Passer des arguments à … parameters

Non – ni l’un ni l’autre Pour les programmeurs Go for C ++ ,

Go ne prend pas en charge la surcharge de fonctions et ne prend pas en charge les opérateurs définis par l’utilisateur.

Je ne parviens pas à trouver une déclaration tout aussi claire selon laquelle les parameters facultatifs ne sont pas pris en charge, mais ils ne sont pas pris en charge non plus.

Vous pouvez encapsuler cela assez bien dans une fonction similaire à celle ci-dessous.

 package main import ( "bufio" "fmt" "os" ) func main() { fmt.Println(prompt()) } func prompt(params ...ssortingng) ssortingng { prompt := ": " if len(params) > 0 { prompt = params[0] } reader := bufio.NewReader(os.Stdin) fmt.Print(prompt) text, _ := reader.ReadSsortingng('\n') return text } 

Dans cet exemple, l’invite par défaut comporte deux points et un espace devant lui. . .

 : 

. . . Cependant, vous pouvez remplacer cela en fournissant un paramètre à la fonction d’invite.

 prompt("Input here -> ") 

Cela se traduira par une invite comme ci-dessous.

 Input here -> 

J’ai fini par utiliser une combinaison de structure de parameters et d’arguments variadiques. De cette façon, je n’ai pas eu à changer l’interface existante consommée par plusieurs services et mon service a pu transmettre des parameters supplémentaires si nécessaire. Exemple de code dans golang playground: https://play.golang.org/p/G668FA97Nu

Je suis un peu en retard, mais si vous aimez une interface fluide, vous pouvez concevoir vos préparateurs d’appels en chaîne comme ceci:

 type myType struct { s ssortingng a, b int } func New(s ssortingng, err *error) *myType { if s == "" { *err = errors.New( "Mandatory argument `s` must not be empty!") } return &myType{s: s} } func (this *myType) setA (a int, err *error) *myType { if *err == nil { if a == 42 { *err = errors.New("42 is not the answer!") } else { this.a = a } } return this } func (this *myType) setB (b int, _ *error) *myType { this.b = b return this } 

Et puis appelez comme ça:

 func main() { var err error = nil instance := New("hello", &err). setA(1, &err). setB(2, &err) if err != nil { fmt.Println("Failed: ", err) } else { fmt.Println(instance) } } 

Ceci est similaire à l’idiome des options fonctionnelles présenté sur la réponse de @Ripounet et bénéficie des mêmes avantages mais présente certains inconvénients:

  1. Si une erreur survient, elle ne sera pas interrompue immédiatement. Par conséquent, elle sera légèrement moins efficace si vous attendez que votre constructeur signale souvent des erreurs.
  2. Vous devrez dépenser une ligne déclarant une variable err et la mettre à zéro.

Il y a cependant un petit avantage possible, ce type d’appels de fonctions devrait être plus facile à intégrer pour le compilateur mais je ne suis vraiment pas un spécialiste.

Le langage Go ne prend pas en charge la surcharge de méthodes, mais vous pouvez utiliser des arguments variadiques comme les parameters facultatifs. Vous pouvez également utiliser interface {} comme paramètre, mais ce n’est pas un bon choix.