Historique de la question :
En Go, il y a souvent des situations où les types intégrés ne suffisent pas et où il est nécessaire de définir un type de données personnalisé avec des méthodes pour encapsuler la logique et étendre la fonctionnalité. Cela se fait en créant des types personnalisés (type) et des méthodes (func (r Receiver) MethodName()).
Problème :
Les développeurs débutants se mélangent souvent les pinceaux — quelle est la différence entre la déclaration d'un nouveau type basé sur un type existant ? Comment implémenter correctement des méthodes ? Comment se pose la question de la copie, du passage par valeur/indicateur ? Ils se trompent sur la visibilité, le type de receveur et le travail avec les structures intégrées.
Solution :
Pour définir un type personnalisé, on utilise le mot-clé type. Les méthodes sont implémentées à l'aide d'un receveur (receiver) — c'est important pour travailler avec des interfaces.
Exemple de code :
type MyInt int func (m MyInt) Double() int { return int(m) * 2 } // Pour les structures : type User struct { Name string Age int } func (u *User) Birthday() { u.Age++ } var u = User{"Alice", 30} u.Birthday() // Age = 31
Caractéristiques clés :
Les types personnalisés héritent-ils des méthodes du type de base ?
Non. Si vous définissez type MyInt int, alors MyInt n'a pas les méthodes de int. Par exemple, l'appel String() ou d'autres méthodes du type de base ne fonctionnera pas.
Peut-on définir des méthodes pour un alias de type ?
Pour un alias (type MyType = ExistingType), ajouter des méthodes n'est pas possible. Les méthodes ne sont définies que pour les nouveaux types (type MyType ExistingType), et non pour les pseudonymes.
Quel receveur utiliser : pointeur ou valeur ?
Si la méthode doit modifier l'objet, il est préférable d'utiliser un pointeur. Un receveur par valeur copie la structure, ce qui peut conduire à un comportement inattendu, si par exemple, la structure contient des champs de tranche et de carte.
Exemple de code :
type Counter struct { value int } func (c *Counter) Inc() { c.value++ } func main() { c := Counter{} c.Inc() // seulement avec un pointeur, la méthode modifiera value }
Un programmeur a créé type MySlice []int et s'attendait à ce que les méthodes []int, par exemple, append, fonctionnent comme des méthodes sur le type MySlice. Au final, il s'est avéré qu'il n'y avait pas de méthodes, et qu'on ne pouvait pas accéder à MySlice comme à []int directement.
Avantages :
Inconvénients :
Un type Counter int a été défini avec une méthode Inc, ce qui a permis de l'utiliser dans plusieurs parties du programme avec une logique partagée et sans code dupliqué.
Avantages :
Inconvénients :
int.