Je sais que les pointeurs dans Go permettent la mutation des arguments d'une fonction, mais cela n'aurait-il pas été plus simple s'ils avaient adopté uniquement des références (avec les qualificatifs const ou mutable appropriés). Nous avons maintenant des pointeurs et pour certains types intégrés comme les cartes et les canaux passent implicitement par référence.
Suis-je en train de manquer quelque chose ou les pointeurs de Go sont-ils une complication inutile?
J'aime vraiment l'exemple tiré de http://www.golang-book.com/8
func zero(x int) {
x = 0
}
func main() {
x := 5
zero(x)
fmt.Println(x) // x is still 5
}
en contraste avec
func zero(xPtr *int) {
*xPtr = 0
}
func main() {
x := 5
zero(&x)
fmt.Println(x) // x is 0
}
Les références ne peuvent pas être réaffectées, contrairement aux pointeurs. Cela seul rend les pointeurs utiles dans de nombreuses situations où les références ne peuvent pas être utilisées.
Les pointeurs sont utiles pour plusieurs raisons. Les pointeurs permettent de contrôler la disposition de la mémoire (affecte l'efficacité du cache du processeur). Dans Go, nous pouvons définir une structure où tous les membres sont en mémoire contiguë:
type Point struct {
x, y int
}
type LineSegment struct {
source, destination Point
}
Dans ce cas, les structures Point
sont intégrées dans la structure LineSegment
. Mais vous ne pouvez pas toujours intégrer directement les données. Si vous souhaitez prendre en charge des structures telles que des arbres binaires ou une liste liée, vous devez prendre en charge une sorte de pointeur.
type TreeNode {
value int
left *TreeNode
right *TreeNode
}
Java, Python etc n'a pas ce problème car il ne vous permet pas d'incorporer des types composites, il n'est donc pas nécessaire de différencier syntaxiquement l'incorporation et le pointage.
Une alternative possible pour accomplir la même chose est de faire la différence entre struct
et class
comme C # et Swift le fait. Mais cela a des limites. Bien que vous puissiez généralement spécifier qu'une fonction prend une structure comme paramètre inout
pour éviter de copier la structure, elle ne vous permet pas de stocker des références (pointeurs) vers des structures. Cela signifie que vous ne pouvez jamais traiter une structure comme un type de référence lorsque vous trouver cela utile, par exemple pour créer un allocateur de pool (voir ci-dessous).
En utilisant des pointeurs, vous pouvez également créer votre propre allocateur de pool (cela est très simplifié avec beaucoup de contrôles supprimés pour simplement montrer le principe):
type TreeNode {
value int
left *TreeNode
right *TreeNode
nextFreeNode *TreeNode; // For memory allocation
}
var pool [1024]TreeNode
var firstFreeNode *TreeNode = &pool[0]
func poolAlloc() *TreeNode {
node := firstFreeNode
firstFreeNode = firstFreeNode.nextFreeNode
return node
}
func freeNode(node *TreeNode) {
node.nextFreeNode = firstFreeNode
firstFreeNode = node
}
Les pointeurs vous permettent également d'implémenter swap
. Cela consiste à échanger les valeurs de deux variables:
func swap(a *int, b *int) {
temp := *a
*a = *b
*b = temp
}
Java n'a jamais été en mesure de remplacer complètement C++ pour la programmation de systèmes dans des endroits tels que Google, en partie parce que les performances ne peuvent pas être réglées sur la même étendue en raison du manque de capacité à contrôler la disposition et l'utilisation de la mémoire (les échecs de cache affectent considérablement les performances). Go a visé à remplacer C++ dans de nombreux domaines et doit donc prendre en charge les pointeurs.
Go est conçu pour être un langage laconique et minimaliste. Cela a donc commencé avec juste des valeurs et des pointeurs. Plus tard, par nécessité, certains types de référence (tranches, cartes et canaux) ont été ajoutés.
"Il y a beaucoup d'histoire sur ce sujet. Au début, les cartes et les canaux étaient des pointeurs syntaxiquement et il était impossible de déclarer ou d'utiliser une instance sans pointeur. De plus, nous avons eu du mal avec le fonctionnement des tableaux. Finalement, nous avons décidé que la séparation stricte des pointeurs et des valeurs ont rendu le langage plus difficile à utiliser. L'introduction de types de référence, y compris des tranches pour gérer la forme de référence des tableaux, a résolu ces problèmes. Les types de référence ajoutent une complexité regrettable au langage mais ils ont un grand effet sur l'utilisabilité: Go est devenu un un langage plus productif et confortable lors de leur introduction. "
La compilation rapide est un objectif de conception majeur du langage de programmation Go; qui a ses coûts. L'une des victimes semble être la capacité à marquer les variables (à l'exception des constantes de temps de compilation de base) et les paramètres comme immuables. Cela a été demandé, mais refusé.
golang-noix: allez langue. Quelques commentaires et doutes.
"L'ajout de const au système de types le force à apparaître partout et oblige à le supprimer partout si quelque chose change. Bien qu'il puisse être avantageux de marquer des objets immuables d'une manière ou d'une autre, nous ne pensons pas qu'un qualificatif de type const soit à la manière aller."