Skip to content

Instantly share code, notes, and snippets.

@leg0ffant
Last active July 22, 2025 22:32
Show Gist options
  • Select an option

  • Save leg0ffant/3bee4829ce2ad8fd026c to your computer and use it in GitHub Desktop.

Select an option

Save leg0ffant/3bee4829ce2ad8fd026c to your computer and use it in GitHub Desktop.

Revisions

  1. leg0ffant revised this gist Oct 5, 2015. 1 changed file with 62 additions and 5 deletions.
    67 changes: 62 additions & 5 deletions golang-fr.md
    Original file line number Diff line number Diff line change
    @@ -23,15 +23,69 @@ func main() {

    ###### Installation

    sous UNIX Shell
    sous UNIX Shell (`crosh` exemple après shell access mode développeur)

    1. Télécharger la dernière version sur le site golang. Linux amd64 et extraire
    l'archive `tar.gz` avec la commande `tar xvf <fichier.tar.gz>`
    * [Télécharger la dernière version](https://golang.org/dl/ " Site Go DL ")
    sur le site golang. Linux amd64 et extraire
    l'archive `tar.gz` [gzip] avec la commande `tar -xzf <fichier.tar.gz>`

    2. Créer dossier de travail `gocode` inclus dossier `bin` pour binaire et `src`
    `-xzf` est le flag de la commande `tar`, plus d'information shell `tar --help`

    Vous pouvez faire le téléchargement en ligne de commande via


    ```
    wget url/fichier.tar.gz
    ```

    Vérifier le hashage de l'archive, si les données ne sont pas corrompu durant
    le téléchargement algorithme cryptographique `sha1` .

    ```
    sha1sum fichier.tar.gz
    ```

    La suite de chiffre / lettre doit correspondre avec le lien sur le site / server

    Enfin décompresser l'archive dans /usr/local via la commande

    ```
    sudo tar -C /usr/local -xzf ~/Downloads/<fichier>.tar.gz
    ```

    Une fois installer en lançant `/usr/local/go/bin/go` accès aide cmd `go`


    * Créer dossier de travail `gocode` inclus dossier `bin` pour binaire et `src`
    pour code source. Ce positionner dans dossier travail avec la commande `cd`

    3. Compile et test dans `src` via `go build hello.go` puis `./hello`
    * Configurer Gopath

    Gopath permet de gérer la persistance redémarrage et la gestion package et de
    les installer dans le système. Via éditeur ligne de cmd `nano` ou `vi`:

    ```
    $ vi ~/.bashrc
    ```

    Ajoutez en mode insertion `vim` en tapant `i`

    ```
    export PATH=$PATH:/usr/local/go/bin
    export GOPATH=~/Downloads/gocode
    export PATH=$PATH:$GOPATH/bin
    sudo mount -i -o remount,exec /home/chronos/user/
    ```

    Sauvegardez et quitter le fichier en lançant `échap` et cmd `:wq!` sous `vim`


    *Redémarrer ou taper ces 4 lignes commandes dans le shell prise en compte
    immédiate*

    * Compile et test dans `src` via `go build hello.go` puis `./hello`
    * Installer package créer le dossier dans `src` puis `go install hello` & lancer
    en faisant `hello`

    ### Introduction

    @@ -177,6 +231,9 @@ notion de super-information, de paires d'attributs non discernables. Il
    y a impredictibilité de processus déterministes. La cohérence de la paire
    d'attribut admet une information localement inaccessible.

    Pour plus d'information sur la programmation informatique quantique un détour
    sur le [langage Quipper](http://www.mathstat.dal.ca/~selinger/quipper/ "Lien").

    #### Variables, Types et mot-clés

    Pour introduire les bases et les types petit rappel sur l'entier et sa définition
  2. leg0ffant revised this gist Oct 1, 2015. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion golang-fr.md
    Original file line number Diff line number Diff line change
    @@ -2279,4 +2279,5 @@ if f, e := os.Stat("name"); e !=
    * sqlite <https://godoc.org/code.google.com/p/go-sqlite/go1/sqlite3>
    * driver mongoDB noSQL <https://labix.org/mgo>
    * Golang-EN book PDF <https://github.com/golang/go/wiki/Books>
    * Pratique de programmation en Go <https://code.google.com/p/golang-france/downloads/list>
    * Pratique de programmation en Go <https://code.google.com/p/golang-france/downloads/list>
    * Learn <https://github.com/gyuho/learn#contents>
  3. leg0ffant revised this gist Oct 1, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion golang-fr.md
    Original file line number Diff line number Diff line change
    @@ -2275,7 +2275,7 @@ if f, e := os.Stat("name"); e !=
    #### Liens vrac

    * web toolkit <http://www.gorillatoolkit.org/>
    * Site statique <http://gohugo.io/overview/quickstart/>
    * Site statique <http://gohugo.io/overview/quickstart/> + <https://github.com/drone/jkl>
    * sqlite <https://godoc.org/code.google.com/p/go-sqlite/go1/sqlite3>
    * driver mongoDB noSQL <https://labix.org/mgo>
    * Golang-EN book PDF <https://github.com/golang/go/wiki/Books>
  4. leg0ffant revised this gist Oct 1, 2015. 1 changed file with 6 additions and 4 deletions.
    10 changes: 6 additions & 4 deletions golang-fr.md
    Original file line number Diff line number Diff line change
    @@ -2274,7 +2274,9 @@ if f, e := os.Stat("name"); e !=

    #### Liens vrac

    web toolkit <http://www.gorillatoolkit.org/>
    Site statique <http://gohugo.io/overview/quickstart/>
    sqlite <https://godoc.org/code.google.com/p/go-sqlite/go1/sqlite3>
    driver mongoDB noSQL <https://labix.org/mgo>
    * web toolkit <http://www.gorillatoolkit.org/>
    * Site statique <http://gohugo.io/overview/quickstart/>
    * sqlite <https://godoc.org/code.google.com/p/go-sqlite/go1/sqlite3>
    * driver mongoDB noSQL <https://labix.org/mgo>
    * Golang-EN book PDF <https://github.com/golang/go/wiki/Books>
    * Pratique de programmation en Go <https://code.google.com/p/golang-france/downloads/list>
  5. leg0ffant revised this gist Oct 1, 2015. 1 changed file with 8 additions and 0 deletions.
    8 changes: 8 additions & 0 deletions golang-fr.md
    Original file line number Diff line number Diff line change
    @@ -59,6 +59,14 @@ opérateurs et les fonctions built-in:

    ```
    % godoc builtin
    /*ou en local dand le navigateur via shell:*/
    % godoc -http=":6060"
    /*Puis dans la barre du navigateur:*/
    http://localhost:6060/pkg/builtin
    ```

    > Go est-il un langage orienté-objet? Oui et non à la fois, Go introduit la
  6. leg0ffant revised this gist Sep 29, 2015. 1 changed file with 7 additions and 1 deletion.
    8 changes: 7 additions & 1 deletion golang-fr.md
    Original file line number Diff line number Diff line change
    @@ -2263,4 +2263,10 @@ if f, e := os.Stat("name"); e !=
    * **hash**
    * **crypto/aes**
    * **crypto/md5**


    #### Liens vrac

    web toolkit <http://www.gorillatoolkit.org/>
    Site statique <http://gohugo.io/overview/quickstart/>
    sqlite <https://godoc.org/code.google.com/p/go-sqlite/go1/sqlite3>
    driver mongoDB noSQL <https://labix.org/mgo>
  7. leg0ffant created this gist Sep 29, 2015.
    2,266 changes: 2,266 additions & 0 deletions golang-fr.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,2266 @@
    Cours langage GO - annotation - Anthony Le Goff
    - - -

    #INTRO ALGORITHME SOUS GO
    *De l'écriture du premier programme à la logique informatique golang*

    <http://golang.org>

    Premier programme et présentation de "hello world"

    code `hello.go`

    ```
    package main
    import "fmt" // Implémentation formatage I/O module package main
    /* Début du bloc avec accolade fonction main afficher qqchose */
    func main() {
    fmt.Printf("Hello, chrome os\n have fun こんにちは世界\n")
    }
    ```

    ###### Installation

    sous UNIX Shell

    1. Télécharger la dernière version sur le site golang. Linux amd64 et extraire
    l'archive `tar.gz` avec la commande `tar xvf <fichier.tar.gz>`

    2. Créer dossier de travail `gocode` inclus dossier `bin` pour binaire et `src`
    pour code source. Ce positionner dans dossier travail avec la commande `cd`

    3. Compile et test dans `src` via `go build hello.go` puis `./hello`

    ### Introduction

    La programmation en GO est un langage informatique développé à l'origine par
    Robert Griesemer, Rob Pike, Ken Thompson, Ian Taylor, Google en 2007. Le public
    qui est familiarisé avec certain type de langage tels
    que:

    * C
    * C++
    * Perl
    * Java
    * Erlang
    * Scala
    * Haskel

    Aurons moins de mal à appréhender la programmation Go dont il est inspiré.
    Ex: Docker est un programme jeune et populaire développé en Go sous Github.
    Go est un langage orienté pour "systèmes et les réseaux" prisé par le C & C++ .
    Cela n'empêche pas de développer en Go web server ou encore apps smartphone. Il
    est possible de trouver bien de la documentation en Go sur le site officiel à
    l'adresse <http://golang.org/doc/> Egalement la documentation spécifique est
    disponible sous un programme nommé ```godoc``` exemple d'utilisation avec les
    opérateurs et les fonctions built-in:

    ```
    % godoc builtin
    ```

    > Go est-il un langage orienté-objet? Oui et non à la fois, Go introduit la
    notion d'interface qui est un ensemble de méthodes, une fonction peut être
    attachée à un type, ou encore l'héritage multiple
    ainsi que pour définir une structure de Tache grâce au constructeur.

    **Clair et Simple**
    Go à pour but en quelques lignes de code de pouvoir faire beaucoup de chose

    **Concurrent**
    Go permet de parallelisé des taches à l'intérieur d'espace d'adressage,
    à travers des processus et des coeurs multiple de processeur grâce au goroutine

    **Canaux**
    La communication à travers des Goroutines est faîte via canal

    **Rapidité**
    La compilation est rapide, plus rapide que la compilation en C mesuré en Seconde.

    **Format standard**
    La règle est simple, la sortie du filtre ```gofmt``` est le format officiel

    **Type postfix**
    Le Type est donnée après le nom variable comme ```var a int``` au lieu de
    ```int a;``` comme on retrouve en C.

    **UTF-8**
    UTF-8 est partout, dans les strings et le code. Final il est possible utiliser
    dans le code source Φ = Φ + 1

    **Open Source**
    La licence Go est entièrement open source, voir le fichier LICENSE dans le
    code source de la distribution Go.

    #### Définition Algorithme

    La langage Go est abordé en parallèle à introduire l'algorithme informatique au
    niveau des notes prise pour le lecteur.
    L’**algorithmique** est l’ensemble des règles et des techniques
    qui sont impliquées dans la définition et la conception
    d’[algorithmes](http://fr.wikipedia.org/wiki/Algorithme),
    c’est-à-dire de processus systématiques de résolution
    d’un problème permettant de décrire les étapes vers le résultat.
    En d’autres termes, un algorithme est une suite finie et non-ambiguë
    d’instructions permettant de donner la réponse à un problème.

    L’information est la matière première de l’informatique
    . Les algorithmes, qui sont constitués d’informations, stockent,
    manipulent et transforment d’autres informations, à l’aide de machines traité
    sous forme de programme avec son code source.
    Tout, en informatique, est représenté comme une séquence de 0 et de 1 :
    les algorithmes, ou plutôt les programmes,le contenu d’un livre, une photo,
    une vidéo...

    ###### Vous avez dit binaire?

    La base binaire est le langage machine, il ne comprend que des *suites* de 001011
    il y a une raison théorique et technique de l'utilisation du binaire:

    * On ne peut pas faire plus simple que 2 symboles (0, 1) avec un *symbole* plus
    rien ne fonctionne
    * Les symboles 0 et 1 sont transposables électroniquement par: le courant passe
    ou ne passe pas. Réprésente donc toutes les informations sous forme de *bits*
    ( binary digit = chiffre binaire). La quantité d'information est justement le
    nombre de bit nécessaires pour représenter cette information.
    * Le stockage de l'information binaire progresse niveau technique et
    l'utilisation du Qbit comme base computation ou le spin de l'électron dans la
    théorie quantique est "up" = 1 ou "down" = 0 ou l'Etat du système admet une
    information intriquée.

    ###### Base et unité

    * Le *bit* (binary digit) est l'unité d'information: par 0 ou 1
    * L'octet est un groupe de 8 bits (octet en anglais = bytes)

    La mémoire (disque dur, mémoire flash...) sa taille est indiqué en système
    SI internationnal multiplicateur 10³ (symbole k,M,G,T pour kilos, Mega, Giga et
    Tera) et pour les multiplicateurs 2¹⁰ etc symbole Ki, Mi, Gi,etc pour kibi, mébi
    et gibi particulièrement en informatique. Base 2.

    Les bases ont retrouve plusieurs familles et conversion en informatique:

    * Décimale base 10 (0,1,2,3,4,5,6,7,8,9)
    * Binaire base 2
    * Hexadécimal base 16 (0,1,2...A,B,C,D,E,F)

    ###### La théorie systémique

    Point a abordé et la notion de machine introduit par la *cybernétique* et englobant
    un domaine bien plus large tels que la théorie des *systèmes* commencé année 1950
    avec von bertalanffy sur les systèmes biologiques. Trois directions:

    * Le systémisme qui apporte le principe de complexité
    * Un autre systémisme abordé sur quelques choses de plus vague, sur quelques
    vérité holistiques sans devenir opérantes (ni réelle, ni formel, ambigu & fantome)
    * Il y a le *system analysis* qui est le correspondant systémique de l'*engineering*
    cybernétique en opération réductrice mais transdisciplinaire.

    ###### La théorie des constructeurs

    La programmation évolue et l'on voit l'accès à l'informatique quantique grand
    public. Dans cet évolution une théorie de l'information quantique a évolué
    de l'information classique et l'avènement de l'utilisation du *Qbit* `
    quantum-bits`.
    Le caclcul quantique via *RF SQUID* et l'information quantique appartient
    notion de super-information, de paires d'attributs non discernables. Il
    y a impredictibilité de processus déterministes. La cohérence de la paire
    d'attribut admet une information localement inaccessible.

    #### Variables, Types et mot-clés

    Pour introduire les bases et les types petit rappel sur l'entier et sa définition
    par la variable **int**

    ```
    Type int
    >>> 2009 # décimal
    2009
    >>> 0b11111011001 # binaire
    2009
    >>> 0o3731 # octal
    2009
    >>> 0x7d9 # hexadecimal
    2009
    ```

    Important que de ce rappeler que les bases ont un préfixe **0b**, **Oo**, **0x**

    En langage Go la syntaxe ce réfère énormément au langage C avec un point qui rend
    fou les codeurs pour débuggué le programme: la fin du ";" et le calvaire trouver
    celui qui était manquant dans le programme le rendant impossible à compiler. La
    différence majeur au niveau des variables par rapport aux autres langages, elle
    est specifié après le nom variable tels que:

    ```
    Pas int a, mais plutôt a int
    ```

    Donc après **var** a **int** sa valeur assigné est de 0. Avec **var** s **string**
    la valeur zéro de la string vaut "". Déclaré et assigné en Go est deux process.

    Déclaration avec **=**

    ```
    var a int
    var b bool
    a = 15
    b = false
    ```

    Déclaration avec **:=**

    ```
    a := 15
    b := false
    ```

    L'utilisation de **:=** est essentiellement pour les variables déclarés dans les
    fonctions. Multiple déclaration de variable peuvent être groupé et ```const``` &
    ```import``` autorise cela. Ecriture:

    ```
    var (
    x int
    b bool
    )
    ```

    Multiple variable peuvent être assigné sur une ligne également:``` var x,y int ```
    Ou encore un assignement en parallèle:
    ```
    a, b := 20, 16
    ```

    Les **booléens** sont de type **bool** et prennent la valeur de test de condition
    tout ou rien "TOR" *true* ou *false*
    Les variables numériques, il faut prendre en compte le cas des virgules flottantes.
    La déclaration de *nombre réel à virgule flottante* ce fait de cet manière soit en
    **float32** ou **float64** au niveau du type au besoin de l'architecture.

    ```
    // déclaration de la constante Pi
    const Pi = 3.14159
    // déclaration variable rayon en virgule flottante
    var rayon float32 = 1.0
    ```

    ###### Chaine de caractère Strings

    L'un des principaux buit-in type est **string**. Affectation valeur chaine de
    caractère ce fait de cet façon rapide``` s := "Hello World!"```. En Go string
    prend une valeur d'encodage en UTF-8 entre double citation. Un petit exemple
    pour changer la première valeur de la string *"Hello World"* en Go.

    ```
    s := "hello World"
    c := []rune(s)
    c[0] = 'c'
    s2 := string(c)
    fmt.Printf("%s\n", s2)
    ```

    Explication:

    * Converti s en une *array* de **runes**
    * Change le premier élement de cet *array*
    * Créer une nouvelle **string** s2 avec modification
    * Enfin print la valeur de la **string** dans fmt.Printf

    *Multiple string*

    Ecrire des strings et assemblage sur plusieurs lignes:

    ```
    s := "Starting part" +
    "Ending part"
    // OU utilisant raw string et (`)
    s := `Starting part
    Ending part`
    ```

    ###### Runes

    *Rune* est un alias pour **int32** encodé en UTF-8. Permet d'instancer, itération
    de caractère de string. Possible de faire loop sur chaque octets. Problème encodage
    string en 8-bit ASCII ne sont pas intégré en Go.

    ###### Nombres complexes

    Go a en natif le support des nombres complexes sans librairies. Le type de variable
    est nommé ```complex128```(64 bit réel et partie imaginaire) ou ```complex64```
    (32 bit réel et partie imaginaire). Règle:

    > Complexe écrit comme re + im*i* ou `re` est partie réel et `im` imaginaire
    ```
    var c complex64 = 5+5i;fmt.Printf("Value is: %v", c) // %v défault format valeur
    /* Après compilation et lancement */
    print: (5+5i)
    ```

    ###### Errors

    Dans des programmes il est nécessaire de reporter des erreurs, le built-in Go
    permettant cela s'appel **error** et ce déclare `var e error` valeur 'nil'. Ce
    type est une interface.

    #### Opérateur et fonction built-in

    *Opérateur arithmétique*

    ```
    20 + 3 # 23
    20 - 3 # 17
    20 * 3 # 60
    20 / 3 # 6.666666666666667
    20 % 3 # 2 (modulo)
    abs(3 - 20) # valeur absolue
    ```

    *Type booléen*

    ```
    Deux valeurs possibles : False, True.
    • Opérateurs de comparaison : == (egal), != (strict different), >, >=, < et <= :
    2 > 8 # False
    2 <= 8 < 15 # True
    /*Cette optimisation est appelée « principe du shortcut »*/
    (3 == 3) || (9 > 24) # True (dès le premier membre)
    (9 > 24) && (3 == 3) # False (dès le premier membre)
    /* Opérateurs logiques */
    && ET logique,
    || OU logique,
    ! négation logique
    ```

    *Opérateur bit à bit*

    ```
    & ET logique bit à bit,
    | OU logique bit à bit,
    ^ OU EXCLUSIF bit à bit,
    ~ complément binaire ou négation bit à bit,
    /* opérateurs il faut ajouter*/
    << décalage binaire à gauche
    >> décalage binaire à droite
    ```

    #### Algorithme d'Euclide

    L’algorithmique est bien plus ancienne que l’informatique, que l’ordinateur, et
    que le langage Go, utilisé dans ces notes.
    Les exemples les plus anciens et célèbres sont :

    * les calculs d’impôts Babyloniens (il y a 4000 ans)
    * le calcul du plus grand diviseur commun (Euclide, vers −350)
    * les première méthodes de résolution systématique d’équations (Al Khawarizmi,
    ixe siècle)

    Les algorithmes étaient donc d’abord utilisés «à la main».
    Aujourd’hui on entend généralement par algorithmique la réflexion préliminaire
    à l’écriture d’un programme d’ordinateur,
    c’est à dire la recherche d’une méthode systématique et non ambiguë pour
    résoudre un problème. C’est
    la partie conceptuelle de la programmation, l’abstraction 1 d’un programme
    d’ordinateur.
    L’algorithmique est parfois considérée comme une branche des mathématiques,
    parfois comme une branche de l’informatique.
    Les notions d’algorithme, puis d’ordinateur ont été formalisées dans les
    années 30 et 40 par : Kurt Gödel, Alan Turing, John von Neumann...
    Avoir des notions en algorithmique permet de développer soi-même des programmes,
    et/ou d’avoir une discussion constructive avec une équipe de développeurs.
    *Les compétences en algorithmique
    font aussi partie du bagage minimum d’un scientifique, qu’il soit technicien,
    chercheur, ingénieur ou simplement curieux.*

    Ecriture exemple Algorithme d'Euclide

    > Étant donnés deux entiers, retrancher le plus petit au plus
    grand et recommencer jusqu’à ce que les deux nombres
    soient égaux. La valeur obtenue est le plus grand diviseur
    commun.

    Dans cet idée, on introduit le principe des **structures de controle** c-a-d
    on repart sur la base *si* et *sinon* `[if, else]` permettant de faire des boucles. Le
    *while* équivaut à "répéter" en français disparait en langage Go au profit de
    **for** et **switch**

    ```
    /*
    ----------------------
    | ALGORITHME EUCLIDE |
    ----------------------
    E1: Formuler l'idée
    ___________________
    Étant donnés deux entiers, retrancher le plus petit au plus
    grand et recommencer jusqu’à ce que les deux nombres
    soient égaux. La valeur obtenue est le plus grand diviseur
    commun.
    E2: Décrire étapes
    __________________
    a,b : deux nombres
    Répéter tant que a et b sont différents :
    si le plus grand est a :
    les deux nombres deviennent a−b et b
    sinon (b est donc le plus grand) :
    les deux nombres deviennent a et b−a
    le pgcd est a
    Les espaces equivaut à l'indentation, ici = 4 (test et
    répétition de tâche)
    E3: Algorithme formel
    _____________________
    fonction pgdc(a,b : entiers)
    repeter tant que a/=b
    si a>b
    a=a−b
    sinon
    b=b−a
    retourner a
    On retrouve premières bases algo avec les boucles (while) et
    test de condition (if, else) Notons que en Go While n'existe pas.
    Il faut donc remplacer par une boucle for et l'accolade = retourner a
    ---------------------------------------
    */
    /* E4: Ecriture programme principale calcul plus grand
    dénominateur commun */
    package main
    import "fmt"
    func main() {
    a := 933
    b := 789
    for a != b {
    if a > b {
    a = a - b
    } else {
    b = b - a
    }
    }
    fmt.Println("le PGDC vaut", a,":", b)
    }
    ```

    La valeur retourner de votre programme après compilation et édition:
    Sauvegarder **pgdc.go** puis dans le dossier de travail lancer `go build pgdc.go`
    enfin pour lancer l'executable bin taper **shell** `./pgdc`

    > Valeur de sortie: *le PGDC vaut 3 : 3*
    Dans ce programme nous avions déclaré deux entiers a = 933 et b = 789. Le plus
    petit diviseur commun valant donc 3 par l'analyse algorithmique d'Euclide. La
    difficulté ici resulte à `print` via un `Println` de *fmt*.
    Cett fonction formate de manière auto tout type paramètre. Retourne la chaine
    formatée au lieu de l'afficher équivaut à utiliser formatage défaut `%v`. Le
    formatage de texte est le module **fmt**.

    **Programmer** est l’activité qui consiste à :

    * traduire des algorithmes dans un langage de programmation :
    * afin d’obtenir des réponses effectives (souvent numériques) à des problèmes ;
    * afin de se distraire...
    * corriger des erreurs dans un programme ;
    * rester calme...

    > Pour aller plus loin l'idéal programme pouvoir insérer une valeur d'entrée
    à a & b par l'utilisateur et comparer nombres déterminant un pgdc. Non appliqué
    dans l'exemple mais `scanf` du module *fmt* et l'opérateur `&` le font.

    Il est courant d'utiliser controle d'état `return` ou `break` à la fin tels que:

    ```
    if err := Chmod(0664); err != nil { // nil is like C’s NULL
    fmt.Printf(err) // erreur limité au corps du if
    return err
    }
    ```

    On peut utiliser les opérateurs logiques dans les structures de contrôle:

    ```
    if true && true {
    fmt.Println("true")
    }
    if ! false {
    fmt.Println("true")
    }
    ```

    ###### GOTO

    GO utilise le `goto` permet de sauter à un label prédifini dans la fonction
    courante tels que pour un loop:

    ```
    func myfunc() {
    i := 0
    Here: // label du goto LOOP
    println(i)
    i++ // iterateur compteur incrémentation
    goto Here // Jump
    }
    ```

    ###### La boucle For

    En langage Go le `for` s'utilise sous 3 formes:

    ```
    for init; condition; post { } // Comme en C for
    for condition { } // Comme un while
    for { } // boucle infini
    ```

    Example sous l'écriture en C `for` en Go et incrementation compteur

    ```
    sum := 0
    for i := 0; i < 10; i++ { // init; condition; post
    sum += i // reduction écriture de sum = sum + i
    } // i cesse d'exister à la fin de la boucle
    ```

    ###### Le mot-clé range

    Range s'utilise dans le cadre d'un loop pour slices *(tranches)*, arrays
    *(tableau)*, strings, maps, et canaux. `range` est un itérateur qui appel paire
    de clé. Quand il boucle sur slice ou array, il retourne l'index dans le slice
    comme une clé et sa valeur.

    ###### Switch

    Go mot-clé `switch` est flexible. Pas besoin de constante ou entiers, c'est un
    comparateur de valeur via le mot-clé `case` et `default` simplifie:

    ```
    if i == 0 {
    fmt.Println("Zero")
    } else if i == 1 {
    fmt.Println("One")
    } else if i == 2 {
    fmt.Println("Two")
    } else if i == 3 {
    fmt.Println("Three")
    } else if i == 4 {
    fmt.Println("Four")
    } else if i == 5 {
    fmt.Println("Five")
    }
    ```

    Ce programme indique le nom anglais associé à un nombre via `switch` cela donne

    ```
    switch i {
    case 0: fmt.Println("Zero")
    case 1: fmt.Println("One")
    case 2: fmt.Println("Two")
    case 3: fmt.Println("Three")
    case 4: fmt.Println("Four")
    case 5: fmt.Println("Five")
    default: fmt.Println("Unknown Number")
    }
    ```

    #### Fonctions built-in

    Les built-in sont des fonctions inclus sans besoin de faire appel à des librairies
    ou des packages.

    * **close** utilisé canal de communication, ferme un canal
    * **delete** utilisé pour supprimer entrée maps
    * **len** & **cap** sont utilisés pour retourner longueur d'un string ou
    tableau et d'un slice
    * **new** permet d'allouer de la mémoire pour utilisateur défini types données
    * ** make** Utiliser allouer mémoire built-in types (maps, slices, canaux)
    * **copy** permet de copier un slice
    * ** append** concaténation de slice
    * **panic**, **recover** comme mécanisme d'exeption
    * **print**, **println** fonction d'impression bas niveau sans "fmt" debugging
    * **complex**, **real**, **imag** utilisation des nombres complexes

    #### Tableaux, Slices et maps

    Un tableau `array` de valeurs est une série consécutive de valeurs, accessibles
    par leur indice entier, 0,1,2,3... En Go on déclare un tableau en faisant précéder
    le type des éléments par la taille en crochets `var x [5]int` donc **x** nom
    du tableau composé de **5** *entiers*. Test de programme tableau

    ```
    package main
    import "fmt"
    func main() {
    var x [5]int
    x[4] = 100 // Allouer 100 à l'élément 4 du tableau
    fmt.Println(x)
    }
    ```

    **Afficher valeur print**

    > [0 0 0 0 100]
    Un tableau commence toujours par la valeur 0,1,2,3,4..... **Zéro est inclus**

    ###### Calcul de moyenne

    Ici nous allons abordé les tableaux par le calcul de la somme arithmétique de
    valeur pour diviser par le nombre de valeur, équivaut nombre élément dans le
    tableau.

    ```
    package main
    import "fmt"
    func main() {
    var x [5]float64
    x[0] = 17.5
    x[1] = 11
    x[2] = 9
    x[3] = 14.5
    x[4] = 13
    var total float64 = 0
    for i := 0; i < 5; i++ {
    total += x[i] // Incrémente les valeurs du tableau x sur chaque élément
    }
    fmt.Println(total / 5) // Total sur le nombre de valeur
    }
    ```

    Quelques explications sur l'utilisation du tableau

    * On déclare un tableau de **5** élément en virgule flottante
    * Allocation pour chaque élément une valeur = nos notes
    * Déclare variable **total** en virgule flottante entière
    * Boucle **for** et init, condition, post (incrémente supérieur)
    * Calcul bloucle **for** total incrémenté à chaque élément du tableau **x**
    * Println du **total** divisé par 5 (nombre de valeur)

    A partir de cet compréhension du tableau, on va amélioré le code de manière plus
    réduite (**less is more**) en place et optimiser le calcul de valeur moyenne.
    Nouveau programme

    ```
    package main
    import "fmt"
    func main() {
    xs := []float64{17.5,11,9,14.5,13} // composite literale
    total := 0.0
    for _, v := range xs {
    total += v
    }
    fmt.Println(total / float64(len(xs)))
    }
    ```

    * On découvre une nouvelle manière d'interprété un tableau sur une ligne
    * Une boucle for "_" (underscore) à la place "i" car non appelé itérateur +
    **range**
    * Conversion tableau défaut **int** println en **float64** sur un *len* équivaut
    taille du tableau

    ###### Slices

    Un Slice est un seqment d'un tableau `array` qui est indexable et a une longueur.

    `slice != array la longueur est autorisé à changer pour le slice`

    Prenons l'exemple `var x []float64` entre crochet valeur longueur prend **0**
    La taille du tableau est fixe sur une valeur [] donc créé un slice pour
    le modifier en utilisant le built-in `make`

    ```
    x := make([]float64, 5)
    ```

    Il y a un troisième paramètre. Correspond à la capacité du tableau dont le slice
    pointe.

    ```
    x := make([]float64, 5, 10)
    ```

    Dans cet exemple `len(x) = 5 et cap(x) = 10` La règle qui différencie Array &
    Slice est donc que:

    ```
    len(slice)== n ;
    cap(slice)== m ;
    len(array)== cap(array)== m .
    ```

    Une autre manière de créer un slice est en utilisant expression [low : high]

    ```
    arr := []float64{1,2,3,4,5}
    x := arr[1:4]
    ```

    Même si le tableau a **5** élément, notre slice défini [1:4] retourne
    [2,3,4] Ainsi `arr[0:]` équivaut à `arr[0:len(arr)]` et `arr[:5]` correspond à
    `arr[0:5]`

    ###### Copy & append

    Si vous avez besoin d'étendre un slice il y a des built-in fait pour ça tels que
    `append` & `copy`. **Append** alloue un nouveau slice dans le slice éxistant

    ```
    s0 := []int{0, 0}
    s1 := append(s0, 2)
    s2 := append(s1, 3, 4, 5, 7)
    s3 := append(s2, s0...) // Noter 3 petits points
    ```

    > s3 retourne **s3 == []int{0, 0, 2, 3, 5, 7, 0, 0}**
    La fonction **copy** éléments de slice d'une source `src` à la destination `dst`
    et retourne le nombre d'élément copié.

    ```
    var a = [...]int{0, 1, 2, 3, 4, 5, 6, 7}
    var s = make([]int, 6)
    n1 := copy(s, a[0:]) // n1 == 6,s == []int{0, 1, 2, 3, 4, 5}
    n2 := copy(s, s[2:])
    ```

    Le type **map** ce retrouve dans plusieurs langage. En C++ c'est la même chose,
    en Perl on trouve *hashes* et en Python les dictionnaires. Map est une collection
    de paire de clé en désordre. Notion de **clé associée**. Prenons exemple
    `x["clé"] = 10` et supprimons la valeur de la clé.

    ```
    x := make(map[int]int)
    x[1] = 10
    fmt.Println(x[1])
    ```

    Quand on Print la valeur de clé "1" on obtient **10**. Et pour supprimer la clé:

    ```
    delete(x,1)
    ```

    Tableau d'élement périodique en chimie et le type map comme exemple dans un
    programme. 10 élément chimique indexe leur symbole. Print sur la clé "Li" qui
    affiche sa valeur *Lithium*

    ```
    package main
    import "fmt"
    func main() {
    elements := make(map[string]string)
    elements["H"] = "Hydrogen"
    elements["He"] = "Helium"
    elements["Li"] = "Lithium"
    elements["Be"] = "Beryllium"
    elements["B"] = "Boron"
    elements["C"] = "Carbon"
    elements["N"] = "Nitrogen"
    elements["O"] = "Oxygen"
    elements["F"] = "Fluorine"
    elements["Ne"] = "Neon"
    fmt.Println(elements["C"])
    }
    ```

    On peut raccourcir et simplifier le code de cet manière sur type **map**

    ```
    elements := map[string]string{
    "H": "Hydrogen",
    }
    ```

    Cela permet d'une manière général de stocker de l'information. Ajoutons à la
    paire de clé et valeur une autre entrée tels que quelques terres rares

    ```
    func main() {
    LREE := map[string]map[string]string{
    "Y": map[string]string{
    "Nom":"Yttrium",
    "Numéro et masse atomique":"N°39 et ma 88.90",
    },
    "Nd": map[string]string{
    "Nom":"Neodyme",
    "Numéro et masse atomique":"N°60 et ma 144.24",
    },
    "Eu": map[string]string{
    "Nom":"Europium",
    "Numéro et masse atomique":"N°63 et ma 151.25",
    },
    "Dy": map[string]string{
    "Nom":"Dysprosium",
    "Numéro et masse atomique":"N°66 et ma 162.50",
    },
    }
    if el, ok := LREE["Y"]; ok {
    fmt.Println(el["Nom"], el["Numéro et masse atomique"])
    }
    }
    ```

    Le **if** est utilisé pour indéxer une recherche dans le tableau à travers une
    valeur de clé et print ces valeurs: *test d'existence*

    > **Note sur la complexité** la recherche dans map (dictionnaire) en fonction
    nombre de valeur à indéxer admettent un temps de performance des algorithmes.
    Ainsi dans la recherche dichotomique, l'algorithme en *Θ(log(n))* ou
    logarithmique est à préviligié dans l'écriture de boucle de fonction.

    #### Exercices

    *Développement selon John Zelle*

    **Analysez le problème** Comprenez le problème à résoudre et sa nature. Essayez
    d’en apprendre le plus possible sur lui. Vous ne pourrez pas le résoudre
    avant de le connaître parfaitement.

    **Spécifiez le programme** Décrivez très exactement ce que votre programme va
    faire. Vous ne devez pas déjà vous soucier de la façon dont il va le faire,
    mais plutôt décider très exactement ce qu’il va faire. Pour des programmes
    simples, cela consistera à décrire ce que seront les entrées et les sorties du
    programme et ce qui les relie.

    **Concevez le programme** Formulez la structure globale du programme. C’est à ce
    moment que vous traiterez de la façon dont le programme résoudra le problème. Le
    travail principal est de concevoir le ou les algorithmes qui rempliront les
    tâches préalablement spécifiées.

    **Codez** Traduisez les algorithmes conçus dans un langage de programmation et
    entrez les sur un ordinateur. Dans ces notes, nous programmerons nos algorithmes
    en Go.

    **Testez/Débuggez le programme** Essayez votre programme et voyez s’il
    fonctionne comme vous le souhaitiez. S’il y a des erreurs (souvent appelées bugs),
    revenez à l’étape précédente et corrigez les. L’activité qui consiste à débusquer
    et corriger les erreurs s’appelle le debuggage. Durant cette phase, votre
    objectif est de trouver des erreurs, et pour cela, vous devez tester tout ce qui
    vous passe par le tête et qui pourrait planter le programme. Il sera utile de
    garder à l’esprit la maxime :

    > *Nothing is foolproof because fools are too ingenious*
    **Faites de la maintenance** Continuez à développer votre programme en répondant
    aux besoins des utilisateurs. La plupart des programmes ne sont jamais vraiment
    finis ; ils continuent d’évoluer au fil des années d’utilisation.

    ###### Calcul de puissance et Entrée[Input] / Sortie[Output]

    Q1. On va partir sur un programme simple mathématique sur les puissances pour
    introduire la saisie utilisateur. L'idée du programme est de connaitre une valeur
    de la fonction inverse `1/r²` ou **r** est défini par l'utilisateur en début de
    programme. Pour plus d'information sur la fonction 'input'

    ```
    godoc fmt
    ```

    > Rechercher func scanf et utilisation de l'opérateur `&` pour trouver adresse
    de variable

    A1. Solution au problème

    ```
    package main
    import "fmt"
    func main() {
    fmt.Print("Entrée un nombre: ")
    var r float64
    fmt.Scanf("%f", &r) // %f précision pour virgule flottante
    x := 1 / ( r * r )
    fmt.Println("Valeur inverse² :", x)
    }
    ```

    ###### Runes: Comptage de symbole strings

    Q2. Un nouveau problème de poser et les chaines de caractère. Admettons une
    énigme cryptographique sous un langage inconnu de symbole. On ne sait pas ce que
    cela veut dire, mais on aimerait bien compter le nombre de caractère de la chaine.
    Et en addition compter le nombre d'*Octet* de la `string` via module "utf8" voir
    `godoc unicode/utf8` *chaine à analyser:* `⢎𝚿⣟ ⣹𝚲⢪ ⢱𝚵⢧`

    A2. Solution pour compter des runes et des octets. En cherchant dans *godoc* et
    *utf8* on trouve une fonction qui permet de compter les runes `func RuneCount(p []byte)int`
    Pour convertir string vers octets

    ```
    str := "hello"
    b := []byte(str)
    ```

    On ce retrouve donc avec ce programme `runes_count.go`

    ```
    package main
    import (
    "fmt"
    "unicode/utf8"
    )
    func main() {
    str := "⢎𝚿⣟ ⣹𝚲⢪ ⢱𝚵⢧"
    fmt.Printf("String %s\nLength: %d, Runes: %d\n", str,
    len([]byte(str)), utf8.RuneCount([]byte(str)))
    }
    ```

    Valeurs affichées

    > String ⢎𝚿⣟ ⣹𝚲⢪ ⢱𝚵⢧
    > Length: 32, Runes: 11
    Quelques explications sur le formatage de texte de la fonction `printf` et
    l'opérateur `%`

    * suivi d'un “d”, il implique la présence d'un entier et
    le formate en décimal,
    * suivi d'un “s”, il implique la présence d'une chaîne,
    * suivi d'un “x”, il implique la présence d'un entier et
    le formate en hexadécimal,
    * suivi d'un “g”, il implique la présence d'un réel,
    * suivi d'un “v”, il formate de manière automatique
    n'importe quel type,
    * suivi d'un “T”, il affiche le type de la valeur fournie
    * `\n` renvoi à la ligne

    **D'ou**

    * **%s** renvoi à `str`
    * premier **%d** renvoi à `len([]byte(str))`
    * second **%d** renvoi à `utf8.RuneCount([]byte(str))`

    Q3. Enfin de compte les symboles cryptés on peut y insérer d'autre chaine de
    caractère à l'intérieur. Remplacer dans la chaine `⢎𝚿⣟ ⣹ ⢱𝚵⢧ ⣾𝛀⣀ ⣒𝚹⢕` à la
    position 10, 3 runes par `⣹𝚲⢪`

    A3. `runes-copy.go`

    ```
    package main
    import "fmt"
    func main() {
    s := "⢎𝚿⣟ ⣹ ⢱𝚵⢧ ⣾𝛀⣀ ⣒𝚹⢕"
    r := []rune(s)
    copy(r[10:10+3], []rune("⣹𝚲⢪"))
    fmt.Printf("Script symbole original : %s\n", s);
    fmt.Printf("Modification symbolique : %s\n", string(r))
    }
    ```

    Q4. La personne faisant de la rétro-ingénierie sur cette série de symbole codé
    a remarqué qu'il était possible d'obtenir quelque chose de différent en inversant
    le `string`. Après tout cela dépend du sens que nous écrivons que nous faisons
    la compréhension d'un langage! Alors inversé la chaine `⢎𝚿⣟ ⣹ ⢱𝚵⢧ ⣹𝚲⢪ ⣒𝚹⢕`

    A4. programme `reverse.go`

    ```
    package main
    import "fmt"
    func main() {
    s := "⢎𝚿⣟ ⣹ ⢱𝚵⢧ ⣹𝚲⢪ ⣒𝚹⢕"
    a := []rune(s) // Une conversion
    for i, j := 0, len(a)-1; i < j; i, j = i+1, j-1 {
    a[i], a[j] = a[j], a[i] // Assignement parallele
    }
    fmt.Printf("%s\n", string(a)) // Retour converti
    }
    ```

    ### Fonctions

    Une fonction est une section indépendante de code qui maps zéro ou plusieurs
    paramètres d'entrées `INPUT`. Les fonctions sont également appelés *procédures* ou
    des *subroutines*. Les fonctions sont représenté par une boite noire ou un code
    est exécuté par la fonction. Noire car par exemple une voiture est une boite
    noire pour son utilisateur: Il appuie sur l'accélérateur `INPUT` et en sortie le
    véhicule ce déplace `OUTPUT`. Ce ne veut pas dire que vous savez comment marche
    le moteur et tout le processus mécanique derrière. D'ou concept de boite noire.

    > Les notions de boite noire et boite blanche sont très importante pour résoudre
    des niveaux d'abtraction et d'isolation de système, utilisé définir architecture
    ou encore en notation **UML**

    Sur nos programmes Go nous utilisons seulement auparavant une fonction principale
    `func main() {}`

    ```
    Schéma: ---------------
    INPUT | | OUTPUT
    ----- > | Boite noire | ----- >
    | |
    ---------------
    // Déclaration de fonction:
    type mytype int
    func (p mytype) funcname(q int) (r,s int) { return 0,0 }
    ```

    * **func** le mot-clé est utilisé pour déclarer une fonction;
    * **(p mytype)** possible de donnée un type specifique appelé *receiver* dont
    celui-ci défini *la méthode*;
    * **funcname** est le nom de votre fonction;
    * **(q int)** est la variable d'entrée et copié dans la fonction *pass-by-value*;
    * **(r, s int)** sont les paramètres de variable `return` ;
    * **{ return 0,0 }** corps de la fonction entre accolade;

    Reprenons l'exemple du *calcul de moyenne* un peu auparavant pour construire une
    fonction à partir du `main()`

    ```
    func main() {
    xs := []float64{98,93,77,82,83}
    total := 0.0
    for _, v := range xs {
    total += v
    }
    fmt.Println(total / float64(len(xs)))
    }
    ```

    La moyenne `average` d'une série de nombre est un problème classique dans l'
    algorithminique. Nous allons appeler la fonction `average` avec un *slice* en
    *float64 ainsi qu'un `return` en *float64*. On insert le code avant le `main()`

    ```
    func average(xs []float64) float64 {
    panic("Introuvable")
    }
    ```

    Cela est la signature de la fonction, incluant le paramètre (une liste de nombre)
    qui est nommé **xs** et le type `return`. Le built-in `panic` appel un erreur
    runtime, permet de casser le process, routine de la fonction pour debugger plus
    simplement.

    > Ajoutons maintenant l'algorithme dans la fonction
    ```
    func average(xs []float64) float64 {
    total := 0.0
    for _, v := range xs {
    total += v
    }
    return total / float64(len(xs))
    }
    ```

    et modification sur le `main()`, la variable nommé **xs** pas obligatoire
    sous même nom.

    ```
    func main() {
    xs := []float64{98,93,77,82,83}
    fmt.Println(average(xs))
    }
    ```

    #### Algorithme récursif

    Le paradigme de la programmation fonctionnelle en informatique est important dans
    la manière d'aborder les itérateurs. On utilise la fonction factorielle de manière
    **récursive**, elle suffit à elle même en tant que fonction pour s'appeler.

    ```
    Factoriel, symbole !
    n!= | 1 si n=0
    | n(n - 1)! si n >= 1
    ```

    Code `go`

    ```
    package main
    import "fmt"
    func factorial(x uint) uint {
    if x == 0 { // cas de base
    return 1
    } // cas récursif
    return x * factorial(x-1)
    }
    func main() {
    fmt.Println("Valeur vaut: ", factorial(5)) // calcul 5!
    }
    ```

    Dans cette fonction, la valeur de *n*! n'est pas connue tant que la condition
    terminale (ici `x == 0`) n'est pas atteinte. Le programme *empile* les appels
    récursifs jusqu'à atteindre la condition terminale puis *dépile* les valeurs.
    Exemple `factorial(2)`

    * Si `x == 0`? Non. (`x` vaut 2)
    * Trouver le factoriel de `x – 1`
    * Si `x == 0`? Non. (`x` vaut 1)
    * Trouver le factoriel de `x – 1`
    * Si `x == 0`? Oui, `return 1`.
    * return `1 * 1`
    * return `2 * 1`

    #### Closure

    Il est possible de créer des fonctions à l'intérieur de fonctions

    ```
    func main() {
    x := 0
    increment := func() int {
    x++
    return x
    }
    fmt.Println(increment())
    fmt.Println(increment())
    }
    ```

    `increment` ajoute 1 à la variable `x` défini `main()` Scope. Cet variable est
    accessible via fonction `increment`. Variable est non-local et appelé *closure*
    d'ou `increment` et `x` forme *closure*

    #### Variable & Scope

    ```
    package main
    var a = 6
    func main() {
    p()
    q()
    p()
    }
    func p() {
    println(a)
    }
    func q() {
    a := 9
    println(a)
    }
    ```

    Entre les fonctions et le `main()` les variables sont local ou global.
    `a := 5` est déclaré dans `q()` et la valeur *Print* vaudra : 696

    #### Valeurs de retour multiple

    Go utilise le variable `return` multiple pour une fonction tels que

    ```
    func f() (int, int) {
    return 5, 6
    }
    func main() {
    x, y := f()
    }
    ```

    Cette notation est utilisé pour connaitre une valeur *erreur* à coté d'un résultat
    ou un *booléen* fonctionnant.

    * `x, err := f()`
    * `x, ok := f()`

    #### Defer, panic & recovering

    Go a un état particulier entraine l'éxecution différée d'une commande à la sortie
    d'une fonction courante. Exemple après avoir ouvert fichier `defer` fermeture

    ```
    f, _ := os.Open(filename)
    defer f.Close()
    ```

    `defer` est particulièrement utilisé pour libérer des ressources, que cela soit de
    la mémoire ou des processus.

    Lorsque une erreur survient, durant appel de fonction, il vaut mieux indiqué
    l'erreur par un code `return`. Mais aussi irréversible qui entraine fin du
    programme, on appel la fonction `panic()` et récupéré l'exception lancé via
    *panic* avec `recover()` couplé à `defer`

    ```
    package main
    import "fmt"
    func main() {
    defer func() {
    str := recover()
    fmt.Println(str)
    }()
    panic("PANIC")
    }
    ```

    #### Fonctions variadic

    Les fonctions `variadic` en utilisant `...` avant le type du dernier paramètre
    indique prend zéro ou plus paramètres. Tels que Zéro ou plus `ints`.

    ```
    func myfunc(arg ...int) {}
    ```

    ```
    func add(args ...int) int {
    total := 0
    for _, v := range args {
    total += v
    }
    return total
    }
    func main() {
    fmt.Println(add(1,2,3))
    }
    ```

    #### Exercices

    ###### Switch et moyenne arithmétique

    Q5. Ecrire une fonction qui calcul moyenne *average* d'un `float64` slice et `switch`

    A5. Code Go `average.go`

    ```
    func average(xs []float64) (avg float64) {
    sum := 0.0
    switch len(xs) {
    case 0:
    avg = 0
    default:
    for _, v := range xs {
    sum += v
    }
    avg = sum / float64(len(xs))
    }
    return
    }
    ```

    ###### Paire ou Impaire?

    Q6. Exercice sur l'incrémentation. On veut afficher les dix premiers nombres de 1 à
    10 et connaitre si ceux-ci sont soit paire ou impaire. Utiliser `%` modulo

    A6. Correction. On retrouve deux structures controle `for` et `if/else` et
    l'incrémentation *n+1* ce fait sur la ligne de condition par variable `++`

    ```
    package main
    import "fmt"
    func main() {
    for i := 1; i <= 10; i++ {
    if i % 2 == 0 {
    fmt.Println(i, "paire")
    } else {
    fmt.Println(i, "impair")
    }
    }
    }
    ```

    ###### Récursion: suite de Fibonacci

    Q7. La suite de Fibonacci commence tels que `1,1,2,3,5,8,13...` ou en notation
    mathématique:

    ```
    | F0 = 0
    | F1 = 1
    | Fn = Fn−1 + Fn−2 si n > 1
    ```

    Ecrire une fonction prenant le type `int` donnant plusieurs termes de la suite
    de Fibonacci.

    A7. `fi.go`

    ```
    /*
    Fibonacci sequence
    */
    package main
    import "fmt"
    func fibonacci(value int) []int { // variable "value" func, return slice
    x := make([]int, value) // Init Slice en int et len(value)
    x[0], x[1] = 0, 1
    for n := 2; n < value; n++ {
    x[n] = x[n-1] + x[n-2]
    }
    return x
    }
    func main() {
    for _, term := range fibonacci(11) { // Itérateur range de Fi(11)
    fmt.Printf("%v ", term)
    }
    }
    ```

    ###### Une simple stack LIFO

    En informatique la notion de stack `empile` revient régulièrement, web server,
    algo.

    ```
    i | k |<- [i++] --- push(k)
    | l |pop() -- [i--]-> l
    0 | m |
    Schéma stack LIFO 'last in, first out'
    Stack de la figure réprésenté par : [0:m] [1:l] [2:k]
    ```

    Q8. Construire une stack LIFO avec un nombre fixe *int*. Définir *push* pour
    mettre quelques chose sur la stack et *pop* pour enlever de la fonction *stack*

    A8. En premier nous définissons un nouveau type représente *stack*. Avec une
    `array` (gestion clé) et un index. 10 élements dans la *stack*

    ```
    type stack struc { // struc permet de construire des types avancés
    i int
    data [10]int
    }
    ```

    Maintenant nous devons créer les fonctions *push* et *pop*. En premier défini la
    solution **fausse** d'une solution de *push* et problème pointer.

    ```
    func (s stack) push(k int)
    if s.i+1 > 9 {
    return
    }
    s.data[s.i] = k
    s.i++
    }
    ```

    La fonction fonctionne variable `s` de type `stack`. En utilisant appel
    `s.push(50)` on empile un entier 50 sur a stack. Mais la fonction *push* a
    une copie de `s` et ne fonctionnera pas. Rien n'est empilé sur la stack:

    ```
    var s stack // s comme stack variable
    s.push(25)
    fmt.Printf("stack %v\n", s);
    s.push(14)
    fmt.Printf("stack %v\n", s);
    ---
    prints:
    stack [0:0]
    stack [0:0]
    ```

    Pour résoudre cela on donne à la fonction *push* un *pointer* de la stack d'ou:

    ```
    func (s stack)push(k int) → func (s *stack)push(k int)
    ```

    Pour la création du *pointer* on fait une allocation avec `new()` tels que:

    ```
    s := new(stack)
    ```

    On ce retrouve avec le programme `stack.go`:

    ```
    /*
    Stack LIFO
    */
    package main
    import "fmt"
    // Déclare un nouveau type stack, 10 éléments
    type stack struct {
    i int
    data [10]int
    }
    // Fonction push sur une stack
    func (s *stack) push(k int) {
    s.data[s.i] = k
    s.i++
    }
    // Fonction pop enlève une stack
    func (s *stack) pop() int {
    s.i--
    return s.data[s.i]
    }
    // Déclaration dans main() variabe s comme stack et push valeur
    func main() {
    var s stack
    s.push(25)
    s.push(14)
    fmt.Printf("stack %v\n", s)
    }
    ```

    ###### Fonction de hashage MD5

    Une introduction au algoritme cryptographique et MD5. Retro-ingénierie sur un
    morceau de code d'une fonction.

    ```
    /* MD5Hash
    */
    package main
    import (
    "crypto/md5"
    "fmt"
    )
    func main() {
    hash := md5.New()
    bytes := []byte("kenavo\n")
    hash.Write(bytes)
    hashValue := hash.Sum(nil)
    hashSize := hash.Size()
    for n := 0; n < hashSize; n += 4 {
    var val uint32
    val = uint32(hashValue[n])<<24 +
    uint32(hashValue[n+1])<<16 +
    uint32(hashValue[n+2])<<8 +
    uint32(hashValue[n+3])
    fmt.Printf("%x ", val)
    }
    fmt.Println()
    }
    ```

    Q9. Soit ce morceau de code source, comprendre son fonctionnement et définir
    les différentes étapes en sachant que *le print* vaut :

    ```
    22917d0 d14dbfd0 ad38bb8b e1678dc4
    ```


    ###### Algorithme de tri 'sort'

    ```
    Non trié | 0 | 3 | 12 | -1 | -5 | 5 |
    Trié | -5 | -1 | 0 | 3 | 5 | 12 |
    ```

    Il fonctionne en répètant des étapes qu'une liste doit être trié, compare chaque
    paire d'item adjacent et le tri s'il est au mauvais endroit, passe l'étape s'il
    n'a pas besoin de trier l'item. La fonction s'appelle `bubblesort`

    ```
    /*
    Algorithme formel
    -----------------
    procedure bubbleSort( A : list of sortable items )
    do
    swapped = false
    for each i in 1 to length(A) - 1 inclusive do:
    if A[i-1] > A[i] then
    swap( A[i-1], A[i] )
    swapped = true
    end if
    end for
    while swapped
    end procedure
    */
    ```

    Q.10 Ecrire la fonction de l'algorithme quadratique *complexité en Θ(n
    ²
    )* de tri bubblesort

    A.10 code `bubblesort.go`

    ```
    func main() {
    n := []int{5, -1, 0, 12, 3, 5}
    fmt.Printf("unsorted %v\n", n)
    bubblesort(n)
    fmt.Printf("sorted %v\n", n)
    }
    func bubblesort(n []int) {
    for i := 0; i < len(n) - 1; i++ {
    for j := i + 1; j < len(n); j++ {
    if n[j] < n[i] {
    n[i], n[j] = n[j], n[i]
    }
    }
    }
    }
    ```

    *Tri par sélection*

    Une première idée est de procéder ainsi :

    1. rechercher le plus petit, le mettre au début,
    2. rechercher le second plus petit, le mettre en deuxième position
    3. ...

    ###### Variadic & var args

    Q.11 Ecrire une fonction qui prend un nombre variable `int` et *print* chacun
    d'entre eux sur une ligne séparée.

    A.11 On utilise la syntaxe `...` qui prend un nombre d'argument au hasard

    ```
    package main
    import "fmt"
    func main() {
    prtthem(1, 4, 5, 7, 4)
    prtthem(1, 2, 4)
    }
    func prtthem(numbers... int) { // numbers : slice of ints
    for _, d := range numbers {
    fmt.Printf("%d\n", d)
    }
    }
    ```

    ### Pointeurs

    *Définition d'un pointeur*

    Les pointeurs sont un type important en langage Go. Il s'utilise comme l'adresse
    pointant une valeur. On peut retrouver la valeur et la modifier avec un pointeur.

    Un pointeur est déclaré en faisant précéder le type de donnée pointée par une
    étoile`*` (ie: `*int // pointeur entier`). On prend l'adresse pointant sur une
    donnée en la faisant précédé opérateur `&`:

    ```
    var i = 5
    var j *int = &i // pointeur sur i
    ```

    Exemple sur ce programme, pointeur référence & mémorise:

    *Sans pointeur*

    ```
    func zero(x int) {
    x = 0
    }
    func main() {
    x := 5
    zero(x)
    fmt.Println(x) // x vaut 5
    }
    ```

    *Avec pointeur*

    ```
    func zero(xPtr *int) {
    *xPtr = 0
    }
    func main() {
    x := 5
    zero(&x)
    fmt.Println(x) // x vaut 0
    }
    ```

    #### Adressage &

    L'opérateur `&` référence à l'adresse du pointeur ainsi il est possible de
    savoir l'adresse mémoire du pointeur tels que ce code:

    ```
    var i int // Declare variable entier i
    p = &i // Faire p pointer vers i
    fmt.Printf("%v", p)
    ----
    Print 0x7ff96b81c000a
    ```

    #### Le mot-clé nil

    Le mot clé nil représente un pointeur qui ne pointe sur aucune valeur licite.
    Cela peut représenter la valeur initiale d'un pointeur qui ne pointe vers
    *rien* NULL

    #### Allocation

    ###### fonction new()

    ```
    func one(xPtr *int) {
    *xPtr = 1
    }
    func main() {
    xPtr := new(int)
    one(xPtr)
    fmt.Println(*xPtr) // x is 1
    }
    ```

    `new` prend un argument, alloue de la mémoire pour la valeur du type et retourne
    au pointeur. Les pointeurs sont utilisé en particulier avec `struct` le type
    structuré.

    ###### Utilisation de make pour allouer

    `New()` alloues

    `make()` initialises utilisé seulement pour slices, maps, canaux

    Exemple

    ```
    var p *[]int = new([]int)
    var v []int = make([]int, 100)
    ```

    Retenez
    ```
    v := make([]int, 100)
    ```

    #### Constructeur

    La définition d'un constructeur est une méthode particulière d'initialisation.
    Pour plus d'information liser la doc package `container/ring` et la fonction
    `new` défini un constructeur en Go.

    Exemple avec le package `os`

    ```
    func NewFile(fd int, name string) *File {
    if fd < 0 {
    return nil
    }
    f := File{fd, name, nil, 0} // Create a new File
    return &f // Return the address of f
    }
    ```

    ### Type structuré

    L'idéal serait de construire un programme seulement avec `builtin` type Go,
    ce qui arrive pas toujours avec des besoins spécifique de création.
    Considérer cet exemple intéragi avec des formes:

    ```
    package main
    import ("fmt"; "math")
    func distance(x1, y1, x2, y2 float64) float64 {
    a := x2 - x1
    b := y2 - y1
    return math.Sqrt(a*a + b*b)
    }
    func rectangleArea(x1, y1, x2, y2 float64) float64 {
    l := distance(x1, y1, x1, y2)
    w := distance(x1, y1, x2, y1)
    return l * w
    }
    func circleArea(x, y, r float64) float64 {
    return math.Pi * r*r
    }
    func main() {
    var rx1, ry1 float64 = 0, 0
    var rx2, ry2 float64 = 10, 10
    var cx, cy, cr float64 = 0, 0, 5
    fmt.Println(rectangleArea(rx1, ry1, rx2, ry2))
    fmt.Println(circleArea(cx, cy, cr))
    }
    ```

    #### définir son type avec Struct

    Une façon rapide d'optimiser le programme est d'utiliser `struct` et ces
    paramètres *fields* pour définir Circle

    ```
    type Circle struct {
    x, y, r float64
    }
    ```

    **Initialisation**

    Créer instance type Circle

    ```
    var c Circle
    ```

    Il est possible également d'utiliser la fonction `new()` pour *struct*

    ```
    c := new(Circle)
    ```

    Cela alloue mémoire pour les *fields* mise à zéro et un retour pointeur et ainsi
    redonner une valeur *fields* tels que:

    ```
    c := Circle{x: 0, y: 0, r: 5}
    ```

    **Fields**

    On peut accéder aux *fields* en utilisant l'opérateur `.`

    ```
    fmt.Println(c.x, c.y, c.r)
    c.x = 10
    c.y = 5
    ```

    Modifiant function `CircleArea` avec `Circle`

    ```
    func circleArea(c *Circle) float64 {
    return math.Pi * c.r*c.r
    }
    ```

    Dans le `main()`

    ```
    c := Circle{0, 0, 5}
    fmt.Println(circleArea(&c))
    ```

    **Méthodes**

    On peut encore écrire la fonction d'une autre manière en utilisant une fonction
    particulière nommée *méthode* , dans ce morceau de code on ajoute un *receiver*
    permettant d'appeler une fonction utilisant l'opérateur `.`

    ```
    func (c *Circle) area() float64 {
    return math.Pi * c.r*c.r
    }
    ```

    Dans le print

    ```
    fmt.Println(c.area())
    ```

    On remarque que l'utilisation des pointeurs en Go en utilisant une méthode à
    changé. En Go sait automatiquement ajouter un pointeur pour `Circle` pour cette
    méthode défini. Change rectangle:

    ```
    type Rectangle struct {
    x1, y1, x2, y2 float64
    }
    func (r *Rectangle) area() float64 {
    l := distance(r.x1, r.y1, r.x1, r.y2)
    w := distance(r.x1, r.y1, r.x2, r.y1)
    return l * w
    }
    ```

    Et dans le `Main()`

    ```
    r := Rectangle{0, 0, 10, 10}
    fmt.Println(r.area())
    ```

    #### Exercices

    ###### Pointeurs

    Q.12 . Suppose type structuré est défini:

    ```
    type Person struc {
    name string
    age int
    }
    ```

    Quel est différence entre ces deux lignes?

    ```
    var p1 Person
    p2 := new(Person)
    ```

    Quel est différence entre ces deux allocations?

    ```
    func Set(t *T) {
    x = t
    }
    and
    func Set(t T) {
    x= &t
    }
    ```

    ###### Map Fonction

    ```
    func Map(f func(int) int, l []int) []int {
    j := make([]int, len(l))
    for k, v := range l {
    j[k] = f(v)
    }
    return j
    }
    func main() {
    m := []int{1, 3, 4}
    f := func(i int) int {
    return i * i
    }
    fmt.Printf("%v", (Map(f, m)))
    }
    ```

    Une `map()-function` est une fonction attaché à une liste et une fonction tels
    que:

    > *map(f(),(a1, a2, . . . , an−1, an)) = (f(a1), f(a2), . . . , f(an−1), f(an))*
    Le code ci-dessus est la solution à l'équation pour le type *int*

    Q.13 Ré-écrire la map-fonction avec une interface générique, en typé *int*, *str*

    A.13 code `map-function-gen.go`

    ```
    package main
    import "fmt"
    //* define the empty interface as a type
    type e interface{}
    func mult2(f e) e {
    switch f.(type) {
    case int:
    return f.(int) * 2
    case string:
    return f.(string) + f.(string) + f.(string)
    + f.(string)
    }
    return f
    }
    func Map(n []e, f func(e) e) []e {
    m := make([]e, len(n))
    for k, v := range n {
    m[k] = f(v)
    }
    return m
    }
    func main() {
    m := []e{1, 2, 3, 4}
    s := []e{"a", "b", "c", "d"}
    mf := Map(m, mult2)
    sf := Map(s, mult2)
    fmt.Printf("%v\n", mf)
    fmt.Printf("%v\n", sf)
    }
    ```

    ### Interfaces

    Une interface est un ensemble de *méthodes*, c'est à dire des fonctions qu'il est
    possible d'implémenter pour une type défini. Ce morceau de code défini `struct`
    type `s` avec un `field` qui défini 2 méthodes pour `s`

    ```
    type S struct { i int }
    func (p *S) Get() int { return p.i }
    func (p *S) Put(v int) { p.i = v }
    ```

    En définissant type `interface` `I` de plusieurs méthodes

    ```
    type I interface {
    Get() int
    Put(int)
    }
    ```

    Rappeler vous les méthodes communes pour `Rectangle` & `Circle` ont `area`. En
    définissant une interface nommé `Shape`:

    ```
    type Shape interface {
    area() float64
    }
    ```

    L'interface implémenté en langage Go est une forme de *duck typing*, loin du
    pure *duck typing* car la compliation Go va checké statique le type implémenté
    niveau interface. La conversion checké au moment runtime. Interface est l'idée
    dans d'autres langages comme *pure abstract virtual base classes* en C++,
    *typerclasses* en Haskell ou *duck typing* en python.

    Aucun langage combine comme
    en Go : *Valeur interface, statique type checking, dynamique runtime conversion,
    et pas nécessité déclaré qu'un type satisfait une interface.*

    ### Concurrent

    > “Parallelisme est a propos de la performance;Concurrent est à propos du design
    de programme. *Rob Pike*

    Quand on code de gros programme informatique il est nécessaire plusieurs
    sous-programme. L'exemple du web server dans l'attente réponse du navigateur
    et renvoi à une page HTML en réponse. Chaque requète est comme un
    sous-programme.

    Il serait idéal pour de sous-programme comme ceux-ci de pouvoir les lancer
    en même temps en *parallèle* (surtout multiple requète server et de page web)
    Lancer du multi-tache simultanément s'appel des tâches **concurrent**. Go est
    riche dans l'utilisation concurrent avec `goroutines` et `canaux`

    #### Goroutines

    Une `goroutine` est une fonction capable de lancer en concurrent d'autres
    fonctions. Le mot clé pour utiliser une `goroutine` est `go` puis l'*invocation*
    de fonction.

    ```
    ready("Green Tea", 2) // Appel fonction normal
    go ready("Green Tea", 2) ← ready() lancé comme goroutine
    ```

    ```
    package main
    import "fmt"
    func f(n int) {
    for i := 0; i < 10; i++ {
    fmt.Println(n, ":", i)
    }
    }
    func main() {
    go f(0) // goroutine de f(0)
    var input string
    fmt.Scanln(&input) // permet de tout print avant fin de programme et sortir
    }
    ```

    Ce programme utilise *deux goroutines* l'une implicite le `main()` et la seconde
    à l'appel de `go f(0)`

    Utilisons la fonction `time.Sleep` pour donner un peu de *delay* execution tache

    ```
    package main
    import (
    "fmt"
    "time"
    )
    func ready(w string, sec int) {
    time.Sleep(time.Duration(sec) * time.Second)
    fmt.Println(w, "is ready!")
    }
    func main() {
    go ready("Tea", 2)
    go ready("Coffee", 1)
    fmt.Println("I'm waiting")
    time.Sleep(5 * time.Second)
    }
    ```

    Dans le même style, il est possible d'éxecuter un temps aléatoire avec la fonction
    `rand`

    ```
    import "math/rand"
    amt := time.Duration(rand.Intn(250)) // sur un entier
    ```

    Avant de sortir du programme on attend 5 seconde, l'exemple auparavant on
    demande à l'utilisateur un `scanln`. On peut fixer le problème en utilisant des
    **canaux**

    #### Canaux

    Un canal est comparable à un pipeline en UNIX shell. Le type est spécifique au
    canal. Donc un canal `chan` permet à deux *goroutines* `go` de communiquer
    en eux et de synchroniser leur execution. Créer canal avec *make*

    ```
    ci := make(chan int) // ci integer
    cs := make(chan string) // cs stringe
    cf := make(chan interface{}) // cf interface
    ```

    Pour recevoir et envoyer à un canal on utilise l'opérateur `<-`

    ```
    ci <- 1 // Envoyer integer 1 vers canal ci
    <-ci // Recevoir un integer du canal ci
    i := <-ci // Recevoir du canal ci et le stocker dans i
    ```

    *Fermer un channel*

    ```
    x, ok = <-ch
    ```

    ```
    var c chan int //déclare c variable entier canal
    func ready(w string, sec int) {
    time.Sleep(time.Duration(sec) * time.Second)
    fmt.Println(w, "is ready!")
    c <- 1 // Envoi integer 1
    }
    func main() {
    c = make(chan int) // init c
    go ready("Tea", 2) // lancer goroutine
    go ready("Coffee", 1)
    fmt.Println("I'm waiting, but not too long")
    <-c // Attendre de recevoir du canal 'sans valeur'
    <-c // Deux goroutines donc deux canaux associer valeur.
    }
    ```

    #### select

    L'appel `select` fonctionne comme un `switch` mais dans l'utilisation d'un
    *canal*.

    Modification du programme précédent avec `select`:

    ```
    var c chan int
    func ready(w string, sec int) {
    time.Sleep(time.Duration(sec) * time.Second)
    fmt.Println(w, "is ready!")
    c <- 1 // Envoi integer 1
    }
    func main() {
    c = make(chan int)
    go ready("Tea", 2)
    go ready("Coffee", 1)
    fmt.Println("I'm waiting, but not too long")
    L: for {
    select {
    case <-c:
    i++
    if i > 1 {
    break L
    }
    }
    }
    }
    ```


    #### Parallelisme

    Le langage Go utilise `goroutine` comme concurrent, pour améliorer le parallelisme
    utiliser la fonction `runtime.GOMAXPROCS(n)` qui paramètre le nombre maximum
    de CPU's *processeurs* utiliser pour lancer simultanément.

    ### Communication

    Parlonds rapidement de la communication avec le monde externe. Tels que fichiers,
    dossiers, réseaux ou éxecuter d'autre programme. GO's I/O avec les interfaces:

    ```
    io.Reader et io.Writer
    ```

    Lire à partir d'un fichier

    ```
    package main
    import "os"
    func main() {
    buf := make([]byte, 1024)
    f, _ := os.Open("/etc/passwd") // Ouvrier le fichier
    defer f.Close() // sur de fermer le fichier
    for {
    n, _ := f.Read(buf) // Lecture 1024 octets à la fois
    if n == 0 { break } // fin fichier
    os.Stdout.Write(buf[:n]) // écrire contenu vers os.Stdout
    }
    }
    ```

    Version buffered

    ```
    package main
    import ( "os"; "bufio")
    func main() {
    buf := make([]byte, 1024)
    f, _ := os.Open("/etc/passwd")
    defer f.Close()
    r := bufio.NewReader(f)
    w := bufio.NewWriter(os.Stdout)
    defer w.Flush()
    for {
    n, _ := r.Read(buf)
    if n == 0 { break }
    w.Write(buf[0:n])
    }
    }
    ```

    #### Lancer commands

    Le package `os/exec` a une fonction de lancer des commandes externes. Exemple
    en lançant la commande UNIX `ls -l` affichant chaque fichier,
    information, droit d'accès


    Comparaison script shell UNIX et Go création dossier inexistant

    ```
    Version UNIX Shell
    ------------------
    if [ ! -e name ]; then
    mkdir name
    else
    # error
    fi
    Version Go
    ----------
    if f, e := os.Stat("name"); e !=
    nil {
    os.Mkdir("name", 0755)
    } else {
    // error
    }
    ```

    ### Packages



    ### Package essentiel en Go

    * **fmt**
    * **io**
    * **io/ioutil**
    * **bufio**
    * **sort**
    * **strconv**
    * **strings**
    * **math/rand**
    * **os**
    * **sync**
    * **flag**
    * **time**
    * **sync/atomic**
    * **encoding/json**
    * **encoding/gob**
    * **html/template**
    * **net/http**
    * **net/rpc**
    * **unsafe**
    * **runtime**
    * **reflect**
    * **os/exec**
    * **path/filepath**
    * **errors**
    * **container/list**
    * **hash**
    * **crypto/aes**
    * **crypto/md5**