Chapitre 18
18 - QCM (100 Questions)
> 100 questions à choix multiples pour valider vos connaissances Go, du niveau débutant au niveau expert.
Cours 18 : QCM Go - 100 Questions
300+ lignes de questions à choix multiples pour valider vos connaissances Go.
Module 1 : Syntaxe et types (Q01-Q15)
Q01 - Quelle est la valeur zéro d'une variable de type int ?
A) nil
B) 0
C) -1
D) undefined
Réponse : B — En Go, les variables non initialisées prennent leur valeur zéro. Pour int, c'est 0. nil est la valeur zéro pour les pointeurs, slices, maps, channels, interfaces et fonctions.
Q02 - Quelle est la syntaxe correcte pour déclarer une constante ?
A) const Pi = 3.14
B) final Pi = 3.14
C) let Pi = 3.14
D) var Pi = 3.14
Réponse : A — Go utilise le mot-clé const. Le type est optionnel si le compilateur peut l'inférer.
Q03 - Que retourne len("Go") ?
A) 1 B) 2 C) 4 D) 3
Réponse : B — len sur une chaîne retourne le nombre d'octets (bytes). "Go" fait 2 bytes.
Q04 - Comment déclarer une variable de type int64 ?
A) var x int64 = 10
B) x := 10
C) int64 x = 10
D) var int64 x = 10
Réponse : A — var x int64 = 10. L'inférence de type (:=) déduit int (taille dépend de la plateforme), pas int64.
Q05 - Que fait defer ?
A) Exécute une fonction en parallèle B) Reporte l'exécution d'une fonction à la fin de la fonction courante C) Arrête l'exécution de la fonction D) Crée une goroutine
Réponse : B — defer planifie l'appel d'une fonction juste avant le retour de la fonction englobante.
Q06 - Quel mot-clé est utilisé pour la gestion d'erreurs en Go ?
A) try / catch
B) error / handle
C) if / return (avec le type error)
D) throw / catch
Réponse : C — Go n'a pas de try/catch. Les erreurs sont retournées comme des valeurs et vérifiées avec if err != nil.
Q07 - Que retourne cap(make([]int, 3, 5)) ?
A) 3 B) 5 C) 8 D) 0
Réponse : B — make([]int, 3, 5) crée une slice de longueur 3 et capacité 5. cap retourne la capacité.
Q08 - Quelle est la sortie de fmt.Println(1 << 3) ?
A) 2 B) 4 C) 8 D) 3
Réponse : C — L'opérateur << décale les bits à gauche. 1 << 3 = 8 (binaire : 1 → 1000).
Q09 - Comment transformer un int en float64 ?
A) float64(x)
B) x.(float64)
C) float64(x) — conversion explicite
D) parseFloat64(x)
Réponse : A — float64(x) est une conversion de type explicite en Go.
Q10 - Que vaut !true en Go ?
A) true B) false C) nil D) Erreur de compilation
Réponse : B — ! est l'opérateur de négation logique. !true = false.
Q11 - Quelle déclaration est valide ?
A) var m map[string]int
B) var m map[string]int{}
C) var m := map[string]int{}
D) var m = map[string]int
Réponse : A — var m map[string]int déclare une map nil. Les options B et D sont invalides syntaxiquement. C utilise := avec var.
Q12 - Quelle boucle est équivalente à un while en Go ?
A) for condition { }
B) while condition { }
C) loop { }
D) do { } while condition
Réponse : A — Go n'a qu'une seule boucle : for. for condition {} équivaut à while.
Q13 - Que retourne recover() si appelée en dehors d'un defer ?
A) L'erreur de la panic B) nil C) panic D) Erreur de compilation
Réponse : B — recover() retourne nil si elle n'est pas appelée directement dans une fonction defer. Elle n'est utile que dans un deferred call.
Q14 - Quelle est la portée d'une variable déclarée avec := dans un bloc if ?
A) Globale au package
B) Limitée au bloc if (y compris else/else if)
C) Fonction entière
D) File entière
Réponse : B — Les variables déclarées avec := dans un if sont limitées au bloc if et ses branches else.
Q15 - Comment créer un pointeur vers une variable x ?
A) *x
B) &x
C) ptr(x)
D) new(x)
Réponse : B — &x retourne l'adresse mémoire de x (le pointeur).
Module 2 : Structures et interfaces (Q16-Q25)
Q16 - Comment définir une structure Point avec des champs X et Y ?
A) struct Point { X int; Y int }
B) type Point struct { X int; Y int }
C) class Point { X int; Y int }
D) interface Point { X int; Y int }
Réponse : B — type Point struct { X int; Y int }. Les structures sont définies avec type ... struct.
Q17 - Une interface en Go est satisfaite :
A) Explicitement avec le mot-clé implements
B) Implicitement si le type implémente toutes les méthodes
C) En héritant de l'interface
D) En annotant le type
Réponse : B — Go utilise le duck typing structurel. Un type implémente une interface implicitement s'il a toutes les méthodes requises.
Q18 - Quelle méthode l'interface error requiert-elle ?
A) Error() string
B) String() string
C) Error() error
D) Message() string
Réponse : A — L'interface error a une seule méthode : Error() string.
Q19 - Que permet l'exportation d'un champ dans une structure ?
A) Le champ est accessible depuis d'autres packages B) Le champ est accessible seulement dans le même package C) Le champ est accessible seulement dans le même fichier D) Le champ est accessible via réflexion
Réponse : A — Un identifiant exporté commence par une majuscule et est accessible depuis d'autres packages.
Q20 - Quelle est la différence entre une méthode avec un receiver valeur et un receiver pointeur ?
A) Aucune différence B) Le receiver pointeur permet de modifier le récepteur C) Le receiver valeur est plus rapide D) Le receiver pointeur ne peut pas être appelé sur une valeur
Réponse : B — Un receiver pointeur (func (p *T) M()) permet à la méthode de modifier le récepteur. Un receiver valeur (func (p T) M()) opère sur une copie.
Q21 - Quelle syntaxe permet de vérifier si une interface v est de type string ?
A) v == string
B) v.(string)
C) typeof(v) == string
D) v.instanceof(string)
Réponse : B — La type assertion v.(string) extrait la valeur sous-jacente si v est de type string. Sinon elle panic.
Q22 - Que retourne une assertion de type avec la forme s, ok := v.(string) si v n'est pas un string ?
A) Panic
B) ("", false)
C) ("", nil)
D) (nil, false)
Réponse : B — La forme à deux valeurs retourne la valeur zéro et false si l'assertion échoue, évitant la panic.
Q23 - Combien de méthodes l'interface interface{} a-t-elle ?
A) 0 B) 1 C) 2 D) ∞
Réponse : A — interface{} (ou any en Go 1.18+) est l'interface vide, sans aucune méthode.
Q24 - Quel type de données en Go peut avoir des méthodes ?
A) Seulement les structures B) Tout type défini (type nommé) C) Seulement les pointeurs D) Seulement les interfaces
Réponse : B — Tout type défini avec type peut avoir des méthodes, y compris les types basés sur des types primitifs.
Q25 - Qu'est-ce que l'embedding de types ?
A) L'héritage de classe B) L'inclusion d'un type dans une structure sans nom de champ C) La compilation conditionnelle D) L'import de packages
Réponse : B — L'embedding (ou composition) permet d'inclure un type anonymement dans une structure, héritant de ses méthodes.
Module 3 : Concurrence - Goroutines (Q26-Q35)
Q26 - Comment lancer une fonction f dans une goroutine ?
A) goroutine f()
B) go f()
C) async f()
D) spawn f()
Réponse : B — Le mot-clé go suivi d'un appel de fonction lance une goroutine.
Q27 - Que se passe-t-il si le programme principal se termine avant une goroutine ?
A) La goroutine continue en arrière-plan B) La goroutine est automatiquement terminée C) Le programme panic D) La goroutine est mise en pause
Réponse : B — Les goroutines sont tuées quand le programme principal (main) se termine.
Q28 - Comment synchroniser la fin de plusieurs goroutines ?
A) sync.Mutex
B) sync.WaitGroup
C) sync.Once
D) sync.Cond
Réponse : B — sync.WaitGroup permet d'attendre la fin d'un groupe de goroutines.
Q29 - Quelle est la taille initiale de la pile d'une goroutine ?
A) 1 Mo B) 64 Ko C) 8 Ko D) 2 Ko
Réponse : D — Une goroutine démarre avec environ 2 Ko de pile (contre 1 Mo+ pour un thread OS).
Q30 - Combien de goroutines peuvent s'exécuter simultanément sur un cœur logique ?
A) 1 B) 2 C) Autant que le scheduler Go décide D) Configurable via GOMAXPROCS
Réponse : C — Le scheduler Go multiplexe plusieurs goroutines sur un nombre fixe de threads OS (GOMAXPROCS). Plusieurs goroutines peuvent être en cours d'exécution sur un cœur via le m:scheduling.
Q31 - Que fait runtime.Gosched() ?
A) Termine la goroutine courante B) Suspend la goroutine courante et permet à d'autres de s'exécuter C) Augmente la priorité de la goroutine D) Crée une nouvelle goroutine
Réponse : B — runtime.Gosched() yield le processeur pour permettre à d'autres goroutines de s'exécuter.
Q32 - Que se passe-t-il si une goroutine panic sans recover ?
A) Seule la goroutine panic est terminée B) Tout le programme crash (panic) C) La panic est automatiquement recoverée D) La goroutine est redémarrée
Réponse : B — Une panic non recoverée dans une goroutine fait planter tout le programme.
Q33 - Comment limiter le nombre de threads OS utilisés par le scheduler Go ?
A) runtime.SetMaxThreads()
B) runtime.GOMAXPROCS()
C) os.Setenv("MAXPROCS")
D) runtime.SetCPU()
Réponse : B — runtime.GOMAXPROCS(n) définit le nombre maximum de threads OS pour les goroutines.
Q34 - Quel outil détecte les problèmes de concurrence comme les data races ?
A) go vet
B) go test -race
C) golangci-lint
D) pprof
Réponse : B — Le race detector (go test -race, go run -race) détecte les accès concurrents non synchronisés.
Q35 - Le runtime Go utilise quel modèle de concurrence ?
A) 1:1 (1 goroutine = 1 thread OS) B) M:N (M goroutines sur N threads OS) C) 1:N (1 goroutine sur N threads OS) D) N:1 (N goroutines sur 1 thread OS)
Réponse : B — Le modèle M:N multiplexe M goroutines sur N threads OS, géré par le scheduler Go.
Module 4 : Channels et Select (Q36-Q45)
Q36 - Comment créer un channel non-bufférisé de type int ?
A) make(chan int)
B) make(chan int, 0)
C) new(chan int)
D) create(chan int)
Réponse : A — make(chan int) crée un channel non-bufférisé. make(chan int, 0) est équivalent.
Q37 - Que se passe-t-on si on envoie sur un channel non-bufférisé sans récepteur ?
A) L'envoi réussit immédiatement B) La goroutine se bloque jusqu'à ce qu'un récepteur soit prêt C) Le channel est automatiquement bufferisé D) Une panic est déclenchée
Réponse : B — Un envoi sur un channel non-bufférisé bloque jusqu'à ce qu'une autre goroutine reçoive.
Q38 - Que retourne la réception d'un channel fermé ?
A) La valeur zéro du type B) Une panic C) La dernière valeur envoyée D) nil
Réponse : A — Lire d'un channel fermé retourne immédiatement la valeur zéro du type. La forme à deux valeurs (v, ok := <-ch) retourne false pour ok.
Q39 - Qui doit fermer un channel ?
A) L'expéditeur (sender) B) Le récepteur (receiver) C) N'importe qui D) Le garbage collector
Réponse : A — Seul l'expéditeur doit fermer un channel. Fermer du côté récepteur cause une panic.
Q40 - Que fait select {} (select vide) ?
A) Rien, retourne immédiatement B) Bloque indéfiniment C) Panic D) Compile avec une erreur
Réponse : B — Un select vide bloque indéfiniment. C'est parfois utilisé volontairement (parfois détecté par go vet).
Q41 - Comment implémenter un timeout avec select ?
A) select { case <-ch: ... case <-time.After(timeout): ... }
B) select { case ch <- v: ... default: ... }
C) select { case <-ch: ... }
D) Aucune des réponses
Réponse : A — time.After(timeout) retourne un channel qui envoie après la durée spécifiée, permettant d'implémenter un timeout.
Q42 - Que se passe-t-il si plusieurs cas sont prêts dans un select ?
A) Le premier cas est choisi B) Un cas est choisi aléatoirement C) Tous les cas sont exécutés D) Le programme bloque
Réponse : B — Quand plusieurs cas d'un select sont prêts, Go en choisit un aléatoirement (uniformément).
Q43 - Quelle est la capacité par défaut d'un channel créé avec make(chan int) ?
A) 0 (non-bufférisé) B) 1 C) 10 D) Dépend du type
Réponse : A — make(chan int) crée un channel non-bufférisé (capacité 0).
Q44 - Peut-on range sur un channel ?
A) Oui B) Non C) Seulement les channels bufférisés D) Seulement les channels fermés
Réponse : A — for v := range ch lit du channel jusqu'à ce qu'il soit fermé.
Q45 - Comment créer un channel en lecture seule ?
A) chan<- T (send-only)
B) <-chan T (receive-only)
C) chan T
D) readonly chan T
Réponse : B — <-chan T est un channel en lecture seule. chan<- T est en écriture seule.
Module 5 : Standard Library (Q46-Q55)
Q46 - Comment lire tout le contenu d'un fichier en Go ?
A) os.ReadFile(filename)
B) ioutil.ReadFile(filename)
C) os.Read(filename)
D) file.ReadAll()
Réponse : A — os.ReadFile() (depuis Go 1.16) lit tout le fichier en mémoire. ioutil.ReadFile est déprécié depuis Go 1.16.
Q47 - Quel package gère le formatage de texte avec des templates ?
A) text/template
B) fmt/template
C) template
D) html/template
Réponse : A — text/template pour les templates texte, html/template pour le HTML (avec échappement automatique).
Q48 - Que fait json.NewDecoder(r).Decode(&v) ?
A) Encode v en JSON dans r B) Décode le JSON de r vers v C) Formate v en JSON D) Valide que r est du JSON valide
Réponse : B — json.NewDecoder(io.Reader).Decode(&v) lit et décode un flux JSON à partir d'un reader.
Q49 - Comment créer un serveur HTTP basique ?
A) http.CreateServer()
B) http.Handle("/", handler); http.ListenAndServe(":8080", nil)
C) net.NewServer(":8080")
D) http.Serve(":8080")
Réponse : B — http.Handle enregistre un handler, et http.ListenAndServe démarre le serveur.
Q50 - Quel package est utilisé pour les expressions régulières ?
A) regexp
B) regex
C) re
D) regexp2
Réponse : A — Le package regexp implémente la recherche avec expressions régulières (RE2 syntax).
Q51 - Que retourne strings.Split("a,b,c", ",") ?
A) ["a,b,c"]
B) ["a", "b", "c"]
C) "a b c"
D) ["a", ",", "b", ",", "c"]
Réponse : B — strings.Split sépare une chaîne par un séparateur et retourne une slice.
Q52 - Comment générer une valeur aléatoire sécurisée ?
A) math/rand.Int()
B) crypto/rand.Int()
C) rand.Secure()
D) os.Random()
Réponse : B — crypto/rand fournit des nombres aléatoires cryptographiquement sûrs, contrairement à math/rand.
Q53 - Quel package permet de parser des arguments de ligne de commande ?
A) flag
B) args
C) cmd
D) cli
Réponse : A — Le package standard flag parse les arguments de ligne de commande.
Q54 - Que fait time.NewTicker(d) ?
A) Exécute une fonction après d B) Envoie l'heure actuelle sur un channel à intervalles réguliers C) Crée un timer qui expire après d D) Mesure le temps d'exécution
Réponse : B — time.NewTicker crée un ticker qui envoie l'heure sur son channel à chaque intervalle d.
Q55 - Comment écrire dans plusieurs writers simultanément ?
A) io.Copy(w1, w2, r)
B) io.MultiWriter(w1, w2).Write(p)
C) w1.Write(p); w2.Write(p)
D) io.TeeReader(r, w)
Réponse : B — io.MultiWriter(w1, w2) retourne un writer qui écrit dans tous les writers passés en argument.
Module 6 : Testing et Debugging (Q56-Q65)
Q56 - Quel est le nom de fonction standard pour un test en Go ?
A) TestXxx(t *testing.T)
B) testXxx(t *testing.T)
C) TestXxx(t *testing.T)
D) XxxTest(t *testing.T)
Réponse : C — Les fonctions de test commencent par Test suivi d'une majuscule, avec le paramètre *testing.T.
Q57 - Comment ignorer temporairement un test ?
A) t.Skip()
B) t.Ignore()
C) t.SkipNow()
D) return
Réponse : A — t.Skip() marque le test comme ignoré et arrête son exécution.
Q58 - Que fait go test -v ?
A) Exécute les tests en parallèle B) Affiche la sortie détaillée des tests C) Vérifie la couverture de code D) Exécute seulement les tests échoués
Réponse : B — Le flag -v (verbose) affiche le nom et le résultat de chaque test.
Q59 - Comment exécuter un seul test nommé TestFoo ?
A) go test -run TestFoo
B) go test TestFoo
C) go test -name TestFoo
D) go test -test TestFoo
Réponse : A — -run prend une regex et exécute les tests dont le nom correspond.
Q60 - Quel package permet de créer des mocks en Go standard ?
A) testing/mock
B) testing/iotest
C) mock
D) testify/mock (externe)
Réponse : B — testing/iotest fournit des readers/writers de test. Pour des mocks généraux, on utilise testify/mock ou gomock (externes).
Q61 - Que retourne go tool cover -func=coverage.out ?
A) Un rapport HTML de couverture B) La couverture par fonction C) La liste des fichiers testés D) Les benchmarks
Réponse : B — go tool cover -func affiche le pourcentage de couverture pour chaque fonction.
Q62 - Comment écrire un benchmark en Go ?
A) func BenchmarkXxx(b *testing.B)
B) func BenchXxx(b *testing.B)
C) func BenchmarkXxx(b *testing.Benchmark)
D) func BenchXxx(b *testing.Benchmark)
Réponse : A — func BenchmarkXxx(b *testing.B). Le nom commence par Benchmark.
Q63 - À quoi sert b.N dans un benchmark ?
A) Le nombre d'itérations à exécuter B) Le nom du benchmark C) La durée du benchmark D) Le nombre de goroutines
Réponse : A — Le framework ajuste b.N pour que le benchmark dure suffisamment longtemps.
Q64 - Quelle commande exécute les tests avec le race detector ?
A) go test -race
B) go test -detect
C) go test -data-race
D) go test -thread-safe
Réponse : A — go test -race compile et exécute les tests avec le race detector.
Q65 - Comment capturer la sortie standard dans un test ?
A) En redirigeant os.Stdout et restaurant après
B) testing.CaptureOutput()
C) fmt.Capture()
D) os.CaptureStdout()
Réponse : A — Il faut rediriger os.Stdout manuellement (ou utiliser testing.AllocsPerRun pour les allocations).
Module 7 : Architecture et Patterns (Q66-Q75)
Q66 - Quel est le principe SOLID le plus naturel en Go ?
A) Single Responsibility (facilité par les interfaces) B) Open/Closed C) Liskov Substitution D) Interface Segregation
Réponse : D — Go encourage naturellement l'Interface Segregation Principle avec ses petites interfaces.
Q67 - Quelle est la taille recommandée d'une interface en Go ?
A) Une seule méthode (idiomatique) B) 10+ méthodes C) 100+ méthodes D) Pas de limite
Réponse : A — Les interfaces Go idiomatiques sont petites (1-3 méthodes). "The bigger the interface, the weaker the abstraction."
Q68 - Que signifie "accept interfaces, return structs" ?
A) Les paramètres doivent être des interfaces, les retours des structs concrets B) Préférer les interfaces partout C) Ne jamais retourner d'interfaces D) Utiliser des structs pour les entrées
Réponse : A — C'est un idiome Go : accepter des interfaces (flexibilité), retourner des types concrets (simplicité).
Q69 - Quel pattern est couramment implémenté avec sync.Once ?
A) Singleton B) Factory C) Observer D) Strategy
Réponse : A — sync.Once exécute une fonction une seule fois, parfait pour l'initialisation paresseuse (lazy singleton).
Q70 - Comment implémenter un pipeline de traitement en Go ?
A) Avec des channels connectés B) Avec des goroutines partageant la mémoire C) Avec des callbacks D) Avec l'héritage
Réponse : A — Les pipelines Go connectent des étapes avec des channels, chaque étape dans une goroutine.
Q71 - Le package context est utilisé pour :
A) La gestion de contexte HTTP uniquement B) Le timeout, l'annulation et le passage de valeurs à travers une chaîne d'appels C) La configuration globale D) Les variables d'environnement
Réponse : B — context gère les timeouts, l'annulation et le passage de valeurs à travers les API.
Q72 - Comment implémenter un worker pool en Go ?
A) Un channel de jobs, plusieurs goroutines worker B) Un mutex global C) Des threads dédiés D) Un scheduler manuel
Réponse : A — Le pattern worker pool utilise un channel partagé de jobs et N goroutines qui lisent de ce channel.
Q73 - Qu'est-ce que le "graceful shutdown" ?
A) Arrêter brutalement le serveur B) Arrêter le serveur en terminant les requêtes en cours C) Redémarrer automatiquement D) Mettre à jour sans interruption
Réponse : B — Le graceful shutdown termine les connexions actives avant de fermer le serveur.
Q74 - Comment gérer la configuration d'une application Go ?
A) Variables globales B) Viper ou envconfig C) Fichier JSON lu à la main D) Toutes les approches sont valides
Réponse : B — Viper est la bibliothèque standard de facto pour la gestion de configuration en Go.
Q75 - Dans le pattern repository, quel est le rôle de l'interface ?
A) Définir les opérations de persistence B) Gérer les transactions C) Créer les connexions D) Valider les données
Réponse : A — L'interface Repository définit les opérations de persistence sans exposer l'implémentation.
Module 8 : gRPC et Protobuf (Q76-Q85)
Q76 - Quel type de définition Protobuf utilise Go ?
A) .proto files
B) .go files
C) .pb files
D) .protobuf files
Réponse : A — Les définitions de services et messages sont dans des fichiers .proto.
Q77 - gRPC utilise quel protocole de transport ?
A) TCP B) HTTP/2 C) UDP D) QUIC
Réponse : B — gRPC utilise HTTP/2 comme transport, permettant le multiplexage et le streaming.
Q78 - Quel est le type d'appel gRPC le plus simple ?
A) Unary (requête-réponse) B) Server streaming C) Client streaming D) Bidirectional streaming
Réponse : A — Unary RPC est l'appel classique : une requête, une réponse.
Q79 - Quel format de sérialisation Protobuf utilise-t-il ?
A) JSON B) XML C) Binary (protobuf encoding) D) YAML
Réponse : C — Protobuf utilise un format binaire compact et efficace.
Q80 - Comment le serveur gRPC envoie-t-il un flux de messages ?
A) stream keyword en réponse
B) En écrivant plusieurs fois dans le stream
C) En retournant une slice
D) En utilisant un channel
Réponse : B — Le serveur écrit plusieurs messages dans le même stream avec Send().
Q81 - Quel outil génère le code Go à partir d'un fichier .proto ?
A) protoc avec protoc-gen-go
B) go generate
C) proto-gen
D) protobuf-gen
Réponse : A — protoc --go_out=. --go-grpc_out=. *.proto génère le code Go.
Q82 - Comment gérer l'authentification en gRPC ?
A) Interceptors côté serveur B) En-têtes HTTP C) Metadata API D) Toutes les réponses sont correctes
Réponse : D — gRPC supporte interceptors, metadata, et credentials pour l'authentification.
Q83 - Que sont les gRPC interceptors ?
A) Des middlewares pour gRPC B) Des hooks de base de données C) Des validateurs de requêtes D) Des gestionnaires de logging
Réponse : A — Les interceptors sont l'équivalent des middlewares HTTP pour gRPC.
Q84 - Quel est l'avantage principal de gRPC sur REST ?
A) Plus simple à implémenter B) Performance et typage fort C) Plus de flexibilité D) Compatibilité navigateur
Réponse : B — gRPC offre de meilleures performances (binaire, HTTP/2) et un typage fort avec Protobuf.
Q85 - Comment gérer les erreurs en gRPC ?
A) Codes d'erreur standardisés (gRPC status codes) B) Exceptions C) Codes HTTP D) Messages d'erreur libres
Réponse : A — gRPC utilise des codes d'erreur standardisés (NotFound, Internal, Unavailable, etc.) via le package google.golang.org/grpc/status.
Module 9 : Generics et Avancée (Q86-Q95)
Q86 - Depuis quelle version de Go les generics sont-ils disponibles ?
A) Go 1.16 B) Go 1.18 C) Go 1.20 D) Go 1.22
Réponse : B — Les generics (type parameters) ont été introduits dans Go 1.18.
Q87 - Quelle est la syntaxe pour déclarer une fonction générique ?
A) func F[T any](t T) T
B) func F<T any>(t T) T
C) generic F[T any](t T) T
D) func F(t T) T
Réponse : A — Les paramètres de type utilisent des crochets [].
Q88 - Quelle contrainte permet d'utiliser les opérateurs == et != ?
A) any
B) comparable
C) equatable
D) orderable
Réponse : B — La contrainte comparable permet l'utilisation des opérateurs de comparaison.
Q89 - Peut-on utiliser des generics avec des méthodes sur un type ?
A) Oui B) Non, seulement avec les fonctions C) Oui, avec des méthodes génériques D) Seulement sur les types exportés
Réponse : B — Les méthodes ne peuvent pas avoir leurs propres paramètres de type (contrairement aux fonctions). Seul le type récepteur peut être générique.
Q90 - Quelle est la différence entre any et interface{} ?
A) any est plus rapide
B) Aucune, any est un alias
C) any est plus restrictif
D) interface{} accepte plus de types
Réponse : B — any est un alias pour interface{} introduit en Go 1.18.
Q91 - Comment contraindre un type générique à être un entier signé ?
A) [T int | int8 | int16 | int32 | int64]
B) [T constraints.Signed]
C) [T Signed]
D) [T ~int]
Réponse : A — Il faut énumérer les types ou utiliser golang.org/x/exp/constraints. La contrainte ~int inclut les types basés sur int.
Q92 - Que signifie ~int dans une contrainte ?
A) Exactement le type int
B) int ou tout type dont le type sous-jacent est int
C) int ou uint
D) Tous les entiers
Réponse : B — ~int inclut int et tout type défini comme type MyInt int.
Q93 - L'inférence de type fonctionne-t-elle avec les generics ?
A) Oui, le compilateur peut inférer les types B) Non, les types doivent toujours être explicites C) Oui, mais seulement pour les types primitifs D) Non
Réponse : A — Le compilateur Go infère les paramètres de type dans la plupart des cas.
Q94 - Peut-on utiliser des generics avec des structures de données ?
A) Oui, type Stack[T any] struct { ... }
B) Non
C) Oui, mais seulement les slices
D) Seulement avec des types primitifs
Réponse : A — Les types génériques (structs, etc.) sont supportés : type Stack[T any] struct { items []T }.
Q95 - Quel est un cas d'usage typique des generics en Go ?
A) Implémenter des conteneurs (Stack, Queue, Cache) B) Remplacer toutes les interfaces C) Éviter les goroutines D) Simplifier les import
Réponse : A — Les conteneurs typés (Stack, Queue, Cache, etc.) sont le cas d'usage principal des generics.
Module 10 : Go Runtime et Écosystème (Q96-Q100)
Q96 - Quel est le rôle du garbage collector en Go ?
A) Libérer la mémoire allouée non utilisée B) Gérer les goroutines C) Optimiser le code D) Compiler le code
Réponse : A — Le GC libère automatiquement la mémoire qui n'est plus référencée.
Q97 - Quel type de GC Go utilise-t-il ?
A) Reference counting B) Mark-and-Sweep (concurrent, tri-color) C) Generational D) Manual
Réponse : B — Go utilise un GC concurrent mark-and-sweep avec l'algorithme tri-color.
Q98 - Quel outil permet d'analyser les allocations mémoire ?
A) go tool pprof
B) go tool trace
C) go vet
D) go tool objdump
Réponse : A — go tool pprof avec un profile mémoire (-memprofile) permet d'analyser les allocations.
Q99 - Comment réduire la latence du GC en Go ?
A) Réduire le nombre d'allocations (réutiliser les objets)
B) Augmenter GOGC
C) Utiliser sync.Pool
D) Toutes les réponses
Réponse : D — Réduire les allocations, ajuster GOGC et utiliser sync.Pool aident à réduire la latence du GC.
Q100 - Quel est le modèle de déploiement Go le plus courant ?
A) VM avec JDK B) Binaire statique unique C) Interpréteur D) Container avec interpréteur
Réponse : B — Go compile en un binaire statique unique, facile à déployer (scratch Docker, binaire seul).
Grille de notation
| Score | Niveau | Recommandation |
|---|---|---|
| 95-100 | Expert Go | Vous maîtrisez le langage |
| 80-94 | Avancé | Prêt pour des projets complexes |
| 60-79 | Intermédiaire | Approfondir les concepts faibles |
| 40-59 | Débutant | Revoir les bases du langage |
| 0-39 | Junior | Suivre le cours complet |