Aller au contenu

Programmation Go

Go est un langage de programmation développé par Google, connu pour sa simplicité et sa performance. Il est utilisé pour le développement de logiciels, d'applications web et de systèmes d'exploitation.

Apprendre Go

Questions

  1. Quel est l'intérêt du package main en Go ?
  2. Quelle est la différence entre := et = en Go ?
  3. Quelle est la différence entre var et const en Go ?
  4. Quelle est la différence entre nil et null en Go ?
  5. Quelle est la différence entre panic et error en Go ?
  6. Quel style d'import est préférable entre imports multiples et une seul import groupé ?
  7. Comment exporter un identifiant en Go ?
  8. En Go, le type vient avant ou après le nom de la variable ?
  9. Que singifie une naked return (ou return nu) en Go ?
  10. Dans quel unique endroit peut-on utiliser := ?
  11. Est-ce que Go autorise la conversion implicite de types ?
  12. Combien de types de boucles en Go connaissez-vous ? Quels sont-ils ?
  13. Est-ce Go autorise les switch sans condition (ou sans expression après le switch) ?
  14. Quelle est la différence entre [n]T et []T en Go ?
  15. Est-ce qu'un slice est un nouveau tableau ?
  16. Que font make et append en Go ?
  17. Est-ce que append retourne un nouveau slice ou modifie le slice existant ?
  18. Qu'est-ce qu'une closure en Go ?
  19. Est-ce que Go a des classes ? Si oui, expliquez comment elles fonctionnent. Sinon, expliquer les alternatives.
  20. Quelle est la différence entre une un méthode et une fonction en Go ?
  21. Quelles la différence entre un méthode avec un receveur de type pointeur et un receveur de type valeur ?
  22. Est-ce que Go renvoie une NPE quand on appelle une méthode d'une interface nulle ?
  23. A quoi servent les formateurs %v, %T, %s et %d ?
  24. Expliquer comment gérer les erreurs en Go. Est-ce que Go a des exceptions ?
Réponses
  1. Le package main est le point d'entrée d'une application Go.
  2. := est utilisé pour déclarer et initialiser une variable, tandis que = assigne une valeur à une variable déjà déclarée.
  3. var déclare une variable, alors que const déclare une constante.
  4. nil est utilisé en Go pour désigner l'absence de valeur pour les types de référence, null étant un concept non applicable en Go.
  5. panic est un état d'erreur fatale qui entraîne l'arrêt du programme, alors qu'error est une interface qui peut être gérée.
  6. Il est préférable d'utiliser un import groupé pour améliorer la lisibilité du code.
  7. Pour exporter un identifiant en Go, il doit commencer par une majuscule.
  8. En Go, le type vient après le nom de la variable.
  9. Une naked return est une instruction de retour sans argument, qui retourne les valeurs des variables de retour nommées.
  10. On ne peut utiliser := que dans une fonction.
  11. Go n'autorise pas la conversion implicite de types.
  12. Il existe un seul type de boucles en Go qui est la boucle for.
  13. Go autorise les switch sans condition, qui permettent de simplifier les conditions multiples.
  14. [n]T est un tableau de taille fixe, tandis que []T est une tranche de taille variable.
  15. Un slice est une vue sur un tableau ou un pointeur vers celui-ci.
  16. make est utilisé pour créer des slices, des maps et des channels, tandis que append est utilisé pour ajouter des éléments à un slice.
  17. append retourne un nouveau slice si la capacité du slice est dépassée, sinon il modifie le slice existant.
  18. Une closure est une fonction qui capture les variables de son environnement.
  19. Go n'a pas de classes, mais utilise des structures pour définir des types de données et des méthodes associées, en plus des interfaces pour définir des comportements communs.
  20. Une méthode est une fonction associée à un type, qui peut être appelée sur une instance de ce type.
  21. Une méthode avec un receveur de type pointeur modifie la valeur de l'instance, tandis qu'un receveur de type valeur crée une copie de l'instance.
  22. Go ne renvoie pas de NPE et appelle la méthode avec un receveur nul si elle a un type concret. Néanmoins, si l'interface n'a pas type concret, l'appel de la méthode entraînera une panique.
  23. %v affiche la valeur de la variable, %T affiche le type de la variable, %s affiche la chaîne de caractères et %d affiche un entier.
  24. Les erreurs en Go sont gérées en retournant une valeur d'erreur en plus de la valeur de retour, qui peut être vérifiée et traitée par l'appelant. Go n'a pas d'exceptions, mais utilise des valeurs d'erreur pour signaler les erreurs.

Quelques programmes

Sqrt
package main

import (
    "fmt"
    "math"
)

func Sqrt(x float64) float64 {
    z := 1.0
    previousZ := 0.0
    epsilon := 0.000001
    for i := 0; i < 10 && math.Abs(previousZ-z) > epsilon; i++ {
        previousZ = z
        z -= (z*z - x) / (2 * z)
        fmt.Println(z)
    }
    return z
}

func main() {
    fmt.Println(Sqrt(2), math.Sqrt(2))
    fmt.Println(Sqrt(9), math.Sqrt(9))
}
pic

A lancer depuis l'éditeur en ligne pour avoir un rendu graphique.

package main

import "golang.org/x/tour/pic"

func Pic(dx, dy int) [][]uint8 {
    columns := make([][]uint8, dx)
    for x := 0; x < dx; x++ {
        row := make([]uint8, dy)
        for y := 0; y < dy; y++ {
            row[y] = uint8((x + y) / 2)
            // row[y] = uint8(x ^ y)
        }
        columns[x] = row
    }
    return columns
}

func main() {
    pic.Show(Pic)
}
wordcount
/*
Implement WordCount. It should return a map of the counts of each “word” in the string s.
The wc.Test function runs a test suite against the provided function and prints success or failure.

You might find strings.Fields helpful.
*/
package main

import (
    "strings"

    "golang.org/x/tour/wc"
)

func WordCount(s string) map[string]int {
    counts := make(map[string]int)
    for _, word := range strings.Fields(s) {
        counts[word] = counts[word] + 1
    }
    return counts
}

func main() {
    wc.Test(WordCount)
}
fibclosure
package main

import "fmt"

// fibonacci is a function that returns
// a function that returns an int.
func fibonacci() func() int {
    nm1 := 0
    nm2 := 0

    return func() int {
        n := nm1 + nm2
        nm2 = nm1
        nm1 = n
        if n == 0 {
            nm2 = 1
        }
        return n
    }
}

func main() {
    f := fibonacci()
    for i := 0; i < 10; i++ {
        fmt.Println(f())
    }
}
stringerdemo
package main

import (
    "fmt"
    "strconv"
    "strings"
)

type IPAddr [4]byte

func (ipAddr IPAddr) String() string {
    // Slice of length 0 and capacity 4 (size of array)
    s := make([]string, 0, len(ipAddr))
    for _, v := range ipAddr {
        s = append(s, strconv.Itoa(int(v)))
    }
    return strings.Join(s, ".")
}

func main() {
    hosts := map[string]IPAddr{
        "loopback":  {127, 0, 0, 1},
        "googleDNS": {8, 8, 8, 8},
    }
    for name, ip := range hosts {
        fmt.Printf("%v: %v\n", name, ip)
    }
}
errordemo

readerdemo

rot13reader
/*
source: https://go.dev/tour/methods/23

A common pattern is an io.Reader that wraps another io.Reader, modifying the stream in some way.

For example, the gzip.NewReader function takes an io.Reader (a stream of compressed data) and returns a *gzip.Reader that also implements io.Reader (a stream of the decompressed data).

Implement a rot13Reader that implements io.Reader and reads from an io.Reader, modifying the stream by applying the rot13 substitution cipher to all alphabetical characters.

The rot13Reader type is provided for you. Make it an io.Reader by implementing its Read method.
*/
package main

import (
    "io"
    "os"
    "strings"
)

type rot13Reader struct {
    r io.Reader
}

func (r rot13Reader) Read(b []byte) (int, error) {
    n, err := r.r.Read(b)
    if err != nil {
        return 0, err
    }
    for i := range n {
        if b[i] < 'A' || b[i] > 'z' || (b[i] > 'Z' && b[i] < 'a') {
            continue
        }
        middleLetter := 'M'
        if b[i] >= 'a' {
            middleLetter = 'm'
        }
        if b[i] > byte(middleLetter) {
            b[i] -= 13
        } else {
            b[i] += 13
        }
    }
    return n, nil
}

func main() {
    s := strings.NewReader("Lbh penpxrq gur pbqr!")
    r := rot13Reader{s}
    io.Copy(os.Stdout, &r)
}