Sweetohm

Michel Casabianca


Il est possible de nommer les valeurs de retour d’une fonction Go, mais est-ce une bonne idée ?

Supposons que nous souhaitions écrire une fonction pour parser la ligne de commande, nous pourrions écrire :

func ParseCommandLine2() (*string, *bool, *bool, *string, *bool, *bool) {
	file := flag.String("file", "", "Build file to run")
	info := flag.Bool("info", false, "Print build information")
	version := flag.Bool("version", false, "Print neon version")
	props := flag.String("props", "", "Build properties")
	timeit := flag.Bool("time", false, "Print build duration")
	tasks := flag.Bool("tasks", false, "Print tasks list")
	flag.Parse()
	return file, info, version, props, timeit, tasks
}

Si nous regardons la signature de cette fonction, nous avons :

func ParseCommandLine2() (*string, *bool, *bool, *string, *bool, *bool)

Le moins que l’on puisse dire c’est que ce n’est pas très explicite ! La bulle d’aide pour cette fonction dans VScode sera la suivante et elle ne nous aidera pas beaucoup non plus :

Paramètres non nommés

Nous pouvons écrire une version avec des valeurs de retour nommées comme suit :

func ParseCommandLine() (file *string, info, version *bool, props *string, timeit, tasks *bool) {
	file = flag.String("file", "", "Build file to run")
	info = flag.Bool("info", false, "Print build information")
	version = flag.Bool("version", false, "Print neon version")
	props = flag.String("props", "", "Build properties")
	timeit = flag.Bool("time", false, "Print build duration")
	tasks = flag.Bool("tasks", false, "Print tasks list")
	flag.Parse()
	return
}

La signature de cette fonction est maintenant bien plus explicite :

func ParseCommandLine() (file *string, info, version *bool, props *string, timeit, tasks *bool)

Et sa bulle d’aide le sera tout autant :

Paramètres non nommés

Dans ce cas précis, nous voyons que la version avec valeurs de retour nommées présente un intérêt.

Considérons maintenant la fonction suivante :

func Divide(x, y int) (int, error) {
	if y == 0 {
		return 0, errors.New("division by zero")
	}
	return x / y, nil
}

Cette fonction est assez explicite.

Sa version avec valeurs de retour nommées serait la suivante :

func Divide(x, y int) (result int, err error) {
	if y == 0 {
		result, err = 0, errors.New("division by zero")
	} else {
        result, err = x / y, nil
    }
    return
}

Cette version semble assez étrange à tout développeur Go :

  • Les variables result et err n’ont pas été déclarées dans le corps de la fonction (elle le sont dans la signature de la fonction, ce qui est inhabituel).
  • Le return à la fin de la fonction n’est pas explicite, pour savoir ce qui est retourné, il faut aller voir la signature de la fonction, ce qui est tout aussi inhabituel.
  • Le nommage des valeurs de retour ne présente aucun intérêt car les conventions du Go imposent que l’on renvoie le résultat puis une éventuelle erreur.

Donc dans ce cas précis, cette version avec valeurs de retour nommées ne présente aucun intérêt et est même assez étrange.

Conclusion

Dans l’écrasante majorité des cas, on préférera ne pas nommer les valeurs de retour. Cependant, si le nombre de valeurs de retour est important (ce qui est assez rare), il peut être intéressant de les nommer pour des raisons de documentation.

Enjoy!