samedi 12 août 2023

De Python à Golang: premiers pas

 Passer d'un langage à un autre n'est pas toujours une démarche facile mais constitue un excellent exercice.

Avant de commencer à faire du Go (golang) , il faut retenir 3 choses:

  • La preparation du répertoire projet est importante: on ne peut pas faire un bout de code sur le coin de la table.
  • Il faut un bon IDE : Vscode ou VScodium sont tout à fait adaptés au Go: ils mettent en forme le code automatiquement.
  • La lecture de code Go est le meilleur moyen d'apprendre les bonnes pratiques du langage. Il ne faut pas chercher dans un premier temps à comprendre le code mais plutôt à observer comment le projet s'organise.


Commençons par un exemple simple: Je vais utiliser l'implémentation d'une librairie qui émule le lancer d'un dé en Python pour la transposer en Golang.




Cette classe propose 2 méthodes en plus du constructeur.

En Golang, il n'y pas de mécanisme d'encapsulation comme dans les autres langages, la description de l'objet est portée dans une structure, les fonctions viennent compléter l'ensemble.

type De struct{ Nbface int }
 
 
func (d De) GetFace() int {
	return d.Nbface
}
func (d De) Lance() int {
	n := rand.Intn(d.Nbface) + 1
	return n
}
 
On peut voir que les structures remplacent les classes. Que le 'self' envoyé en coulisse à une méthode Python, prend la forme d'un préfixe de la définition de la fonction en Go.
Comme Go est un langage compilé avec des types de variables statiques, une déclaration du type de la donnée est nécessaire. Mais il existe un sucre syntaxique bien utile l'opérateur ':='. Le type de la donnée d'affectation sera déduit à partir de la partie droite : signature de la fonction, type de la donnée reçue etc.

2 remarques: un élément déclaratif: type , nom de variable, conteneur, fonction etc.. sera utilisable en dehors de son fichier source (exportable) qu'a la condition que son nom commence par une lettre MAJUSCULE.

Utilisation de notre librairie


En python et en Go : par un import.

En python : from libde import De

Puis
En Go :



package main
 
import (
	"fmt"
	"lemonlabs/src/de/libde"
	"sort"
)
 
type De = libde.De
 
func main() {
 
	d1 := De{6}
	fmt.Printf("%v , %T\n", d1, d1)
	fmt.Printf("nb de face :%v\n", d1.GetFace())
	n1 := d1.Lance()
	fmt.Printf("face :%v", n1)
Exécution: go run .\main.go

{6} , libde.De
nb de face :6
face :3

Heritage vs composition.

Soit une classe Depipe qui permet de doubler les chances de sortie d'une face particulière.

En Python, on pourra utiliser les propriétés de l'héritage:

En Go, on utilisera la composition:


type De struct{ Nbface int }
 
type DePipe struct {
	De
	Faceplus int
}
 
A l'exécution de ce code:
d2 := DePipe{
        De{6},
        6,
    }
    fmt.Printf("%v , %T\n", d2, d2)
Avec le résultat suivant:

{{6} 6} , libde.DePipe

Par contre il faudra redevelopper la fonction getface pour depipe au moins d'utiliser une interface. 
(voir les prochains articles)

La suite des fonctions en Go



func (d DePipe) GetFace() int {
	return d.De.Nbface
}
func (d DePipe) Lance() int {
	n := rand.Intn(d.De.Nbface+1) + 1
	if n == d.De.Nbface+1 {
		n = d.Faceplus
	}
	return n
}

Remarque:  la structure qui sera passée aux fonctions Go (GetFace ou Lance) , sera une copie de la structure appelante  (par valeur) . 

Voici pour une première introduction, le source est disponible sur github .
Dans ces exemples, les champs ne sont pas mis à jour. Pour modifier un champ  d'une structure Go, il faudra utiliser un pointeur (dans les prochains articles) .

Aucun commentaire: