Déclarer des variables
En Go, il y a deux façons de déclarer une variable :
package main
import "fmt"
func main() {
// Déclaration longue avec var
var nom string = "Alice"
var age int = 30
// Déclaration courte avec := (la plus utilisée)
ville := "Paris"
score := 42.5
fmt.Println(nom, age, ville, score)
}
La différence ? := est un raccourci qui laisse Go déduire le type automatiquement. Vous l'utiliserez 90 % du temps. var est utile quand vous voulez déclarer une variable sans l'initialiser ou au niveau du package (là où := n'est pas autorisé).
Attention : Go est strict. Si vous déclarez une variable sans l'utiliser, le compilateur refuse de compiler. Zéro gaspillage. Lancez le code ci-dessus et changez une valeur pour voir.
Les types de base
Go est un langage à typage statique : chaque variable a un type fixé à la compilation. Voici les types essentiels :
nom := "Bonjour" // string : chaîne de caractères
age := 25 // int : nombre entier
prix := 19.99 // float64 : nombre décimal
actif := true // bool : vrai ou faux
Contrairement à Python ou JavaScript, vous ne pouvez pas mettre un nombre dans une variable string. Le compilateur vous arrête avant que le bug n'arrive en production.
Go a aussi des types numériques plus précis : int8, int16, int32, int64, float32, float64. Pour débuter, int et float64 suffisent largement.
Constantes
Une constante est une valeur qui ne change jamais. En Go, on utilise const :
const Pi = 3.14159
const AppName = "MonApp"
const MaxRetries = 3
// Pi = 3.0 // Erreur ! On ne peut pas modifier une constante
Les constantes sont évaluées à la compilation, pas à l'exécution. Elles sont plus rapides et plus sûres que les variables.
Pointeurs : & et *
Un pointeur est une variable qui contient l'adresse mémoire d'une autre variable. Deux opérateurs :
On a ce code : func doubler(n int) { n = n * 2 } puis x := 5; doubler(x). Avant de dérouler : après l'appel à doubler(x), que vaut x : 10 ou 5 ? Et comment écrire doubler pour qu'il modifie VRAIMENT la variable de l'appelant ?
Voir la réponse
x vaut toujours 5. En Go, les arguments sont passés par valeur : doubler reçoit une copie de x, et modifier cette copie (n = n * 2) ne touche pas l'original. Pour modifier la variable de l'appelant, on passe un pointeur : func doubler(n *int) { *n = *n * 2 }, appelé avec doubler(&x). &x donne l'adresse de x, et *n (déréférencement) lit et écrit la valeur à cette adresse. Après ça, x vaut 10. Le pointeur, c'est « voici OÙ se trouve ma variable », pas « voici une copie de sa valeur ».
age := 25
ptr := &age // & = "donne-moi l'adresse de age"
fmt.Println(ptr) // 0xc0000b4008 (une adresse mémoire)
fmt.Println(*ptr) // 25 : * = "donne-moi la valeur à cette adresse"
*ptr = 30 // Modifier la valeur via le pointeur
fmt.Println(age) // 30 : age a changé !
& donne l'adresse, * accède à la valeur à cette adresse.Pourquoi les pointeurs ? Quand vous passez une variable à une fonction, Go en fait une copie. Avec un pointeur, la fonction peut modifier la variable originale. C'est essentiel pour l'efficacité.
Structs : créer vos propres types
Un struct regroupe plusieurs champs en un seul type. C'est l'équivalent d'un objet en JavaScript ou d'une classe en Python :
type Person struct {
Name string
Age int
City string
}
func main() {
alice := Person{
Name: "Alice",
Age: 30,
City: "Lyon",
}
fmt.Println(alice.Name) // Alice
fmt.Println(alice.Age) // 30
}
Les structs sont la base de la programmation en Go. Pas de classes, pas d'héritage : juste des structs et des fonctions. Simple et efficace.
À vous d'essayer :
package main
import "fmt"
type Person struct {
Name string
Age int
City string
}
func main() {
ville := "Paris"
score := 42.5
alice := Person{Name: "Alice", Age: 30, City: "Lyon"}
fmt.Println(ville, score)
fmt.Println(alice.Name, alice.Age, alice.City)
}
Declaring variables
In Go, there are two ways to declare a variable:
package main
import "fmt"
func main() {
// Long declaration with var
var name string = "Alice"
var age int = 30
// Short declaration with := (most common)
city := "Paris"
score := 42.5
fmt.Println(name, age, city, score)
}
The difference? := is a shortcut that lets Go infer the type automatically. You'll use it 90% of the time. var is useful when you want to declare a variable without initializing it or at the package level (where := isn't allowed).
Warning: Go is strict. If you declare a variable without using it, the compiler refuses to compile. Zero waste. Run the code above and change a value to see it.
Basic types
Go is a statically typed language — every variable has a type fixed at compile time. Here are the essential types:
name := "Hello" // string — text
age := 25 // int — integer
price := 19.99 // float64 — decimal number
active := true // bool — true or false
Unlike Python or JavaScript, you can't put a number in a string variable. The compiler stops you before the bug reaches production.
Go also has more precise numeric types: int8, int16, int32, int64, float32, float64. For getting started, int and float64 are plenty.
Constants
A constant is a value that never changes. In Go, we use const:
const Pi = 3.14159
const AppName = "MyApp"
const MaxRetries = 3
// Pi = 3.0 // Error! You can't modify a constant
Constants are evaluated at compile time, not at runtime. They are faster and safer than variables.
Pointers: & and *
A pointer is a variable that holds the memory address of another variable. Two operators:
Consider this code: func doubler(n int) { n = n * 2 } then x := 5; doubler(x). Before reading on: after the call to doubler(x), what is x: 10 or 5? And how would you rewrite doubler so it ACTUALLY modifies the caller's variable?
See the answer
x is still 5. In Go, arguments are passed by value: doubler receives a copy of x, and modifying that copy (n = n * 2) does not touch the original. To modify the caller's variable, pass a pointer: func doubler(n *int) { *n = *n * 2 }, called with doubler(&x). &x gives the address of x, and *n (dereferencing) reads and writes the value at that address. After that, x is 10. A pointer means “here is WHERE my variable lives”, not “here is a copy of its value”.
age := 25
ptr := &age // & = "give me the address of age"
fmt.Println(ptr) // 0xc0000b4008 (a memory address)
fmt.Println(*ptr) // 25 — * = "give me the value at this address"
*ptr = 30 // Modify the value via the pointer
fmt.Println(age) // 30 — age changed!
& gives the address, * accesses the value at that address.Why pointers? When you pass a variable to a function, Go makes a copy. With a pointer, the function can modify the original variable. This is essential for efficiency.
Structs: creating your own types
A struct groups multiple fields into a single type. It's the equivalent of an object in JavaScript or a class in Python:
type Person struct {
Name string
Age int
City string
}
func main() {
alice := Person{
Name: "Alice",
Age: 30,
City: "Lyon",
}
fmt.Println(alice.Name) // Alice
fmt.Println(alice.Age) // 30
}
Structs are the foundation of Go programming. No classes, no inheritance — just structs and functions. Simple and effective.
Try it yourself:
package main
import "fmt"
type Person struct {
Name string
Age int
City string
}
func main() {
alice := Person{Name: "Alice", Age: 30, City: "Lyon"}
fmt.Println(alice.Name)
fmt.Println(alice.Age)
}
🎯 Pratique
S'entraîner (clique pour ouvrir) :
✨ Prompt IA
Copiez ce prompt dans Claude ou ChatGPT :
Crée un struct Go "Product" avec un nom, un prix et un stock. Écris une fonction qui applique une réduction de 10% sur le prix. Utilise un pointeur.
💬 Ré-explique sans regarder
Sans relire la réponse de l'IA : pourquoi la fonction de réduction sur le Product a-t-elle besoin d'un pointeur ? Que ferait exactement & et * dedans ?
Product à la fonction, donc baisser le prix ne touche que la copie ; l'original ne change pas. En prenant *Product en paramètre et en appelant avec &monProduit, la fonction reçoit l'adresse ; p.Price = ... (déréférencement implicite, équivalent de (*p).Price) modifie alors la struct d'origine.⚖️ Juge le code de l'IA
L'IA te propose cette fonction de réduction. Ton rôle de relecteur : l'accepter telle quelle ou la rejeter, et dire pourquoi.
func applyDiscount(p Product) {
p.Price = p.Price * 0.9
}
func main() {
laptop := Product{Name: "Laptop", Price: 1000}
applyDiscount(laptop)
fmt.Println(laptop.Price) // 1000
}
p Product (valeur), donc applyDiscount reçoit une copie : la ligne p.Price = p.Price * 0.9 modifie la copie, jamais le laptop d'origine, qui reste à 1000. Le code compile et ne plante pas, mais la réduction est silencieusement perdue : c'est le piège classique du passage par valeur en Go. Le correctif : func applyDiscount(p *Product) et appel applyDiscount(&laptop).🧠 Rappel libre
Sans remonter dans la leçon : quelle différence entre var nom string = "Alice" et nom := "Alice", et que fait le compilateur Go face à une variable déclarée mais jamais utilisée ?
:= est la déclaration courte : Go déduit le type tout seul, et elle ne marche qu'à l'intérieur d'une fonction. var est plus explicite (on peut écrire le type), accepte une déclaration sans valeur initiale et fonctionne aussi au niveau du package. Côté rigueur : une variable déclarée mais jamais utilisée provoque une erreur de compilation (pas un simple avertissement) ; Go refuse de compiler.Vos variables et structs sont en place. On va leur donner vie avec des fonctions qui renvoient plusieurs valeurs, dont la fameuse paire (résultat, error) : vous découvrez pourquoi Go ignore try/catch et gère ses erreurs avec if err != nil, plus le mot-clé defer.
Leçon 3 : Conditions et boucles →