J'apprends aller et je suis un peu confus sur quand utiliser des pointeurs. Spécifiquement, lors du retour d'un Exemple de code: P > struct code> à partir d'une fonction, quand est-il approprié de renvoyer l'instance de struct elle-même, et quand est-il approprié de renvoyer un pointeur sur la structure? type Car struct {
make string
model string
}
func Whatever() {
var car Car
car := Car{"honda", "civic"}
// ...
return car
}
3 Réponses :
Très bien, les exceptions sont susceptibles de se présenter dans des circonstances spécifiques: p>
Souvent, lorsque vous souhaitez imiter un style orienté objet, où vous avez un "objet" qui stocke des éléments d'état et des "méthodes" pouvant modifier l'objet, vous auriez une fonction "constructeur" qui renvoie un pointeur à une structure (pensez-y comme la "référence d'objet" comme dans d'autres langues OO). Les méthodes de mutateur devraient être des méthodes du type pointeur à la structure au lieu du type de structure lui-même, afin de modifier les champs de "objet", il est donc pratique d'avoir un pointeur à la structure au lieu d'une structure au lieu d'une structure. valeur elle-même, de sorte que toutes les "méthodes" seront dans son ensemble de méthodes.
Par exemple, pour imiter quelque chose comme ceci en Java: P>
type Car struct {
make string
model string
}
func NewCar(myMake string) *Car {
return &Car{myMake, ""}
}
func (self *Car) setMake(newMake string) {
self.make = newMake
}
Alors, avec Go, devrais-je ne pas utiliser le mot clé nouveau code>? Je devrais juste retourner une référence comme vous l'illustrez? Je suis confondu par votre exemple.
@Carson: Eh bien, vous pouvez utiliser neuf code>, mais neuf code> initialise la valeur à la valeur zéro du type, qui pour les structures sont tous des champs initialisés à la valeur zéro. Cela pourrait ne pas être une valeur valablement initialisée pour tous les types. Si la valeur zéro est bien pour l'initialisation de votre type, vous pouvez simplement utiliser nouveau code>; Mais si votre type a besoin d'un "constructeur" personnalisé, vous devez définir votre propre fonction comme je l'ai montré
Il y a deux choses que vous voulez garder à l'esprit, la performance et l'API. p>
Comment une voiture est-elle utilisée? Est-ce un objet qui a l'état? Est-ce une grande structure? Malheureusement, il est impossible de répondre quand je n'ai aucune idée de quelle voiture est. Très, le meilleur moyen est de voir ce que les autres font et les copient. Finalement, vous avez un sentiment pour ce genre de chose. Je vais maintenant décrire trois exemples de la bibliothèque standard et expliquera pourquoi je pense qu'ils ont utilisé ce qu'ils ont fait. P>
ai-je répondu à votre question? Probablement pas. C'est une décision de conception et vous devez le comprendre au cas par cas. J'utilise la bibliothèque standard comme guide lorsque je concevons mes propres bibliothèques. Il s'agit vraiment du jugement et de la manière dont vous vous attendez à utiliser vos types. P> hash / crc32 code>: le CRC32 .Neweeeee () code> fonction renvoie un type de pointeur (en réalité, une interface, mais le type sous-jacent est un pointeur). Une instance d'une fonction de hachage a un état. Lorsque vous écrivez des informations sur un hachage, cela résume les données afin que vous appelez la méthode somme () code>, il vous donnera l'état de cette instance. P> LI>
heure code>: le time.date Code> fonction retourne un heure code> struct. Pourquoi? Un temps est un temps. Il n'a aucun état. C'est comme un entier où vous pouvez les comparer, préformez des mathématiques sur eux, etc. Le designer API a décidé qu'une modification à une époque ne changerait pas l'actuelle mais en faire un nouveau. En tant qu'utilisateur de la bibliothèque, si je veux l'heure d'un mois, je voudrais un nouvel objet de temps, de ne pas changer l'actuel que j'ai. Un temps n'est également que 3 mots de longueur. En d'autres termes, il est petit et il n'y aurait pas de gain de performance dans l'utilisation d'un pointeur. P> li>
math / gros code>: Big.Newint () est intéressant. Nous pouvons quasiment d'accord que lorsque vous modifiez un Big.int code>, vous en voulez souvent un nouveau. Un Big.int code> n'a pas d'état interne, alors pourquoi est-ce un pointeur? La réponse est simplement une performance. Les programmeurs ont compris que les gros Ints sont ... grand. Allocation constante chaque fois que vous faites une opération mathématique peut ne pas être pratique. Donc, ils ont décidé d'utiliser des pointeurs et d'autoriser le programmeur à décider quand allouer de nouveaux espaces. P> li>
ol>
J'ai dû lire cela plusieurs fois pour réaliser que c'est une très bonne réponse. Merci.
Très bonne réponse. Je suis nouveau à partir et a été référé ici par Stephen de # Go-Neux sur IRC.
Les mêmes règles ne s'appliquent-elles pas?
Nope, règles différentes pour différentes langues. Toutes les langues ont des mises en garde, et je ne sais personnellement pas aller, donc je ne peux donc pas en parler, mais je sais que dans C, retourner un pointeur sur un objet attribué sur la pile est un non-no non.
Je suis dérangé par les réponses: je pense que la zone grise est liée à des performances sur de petits objets et je ne vois aucun moyen d'estimer la solution la plus rapide du profilage. Est-il simplement plus rapide de passer par des objets de valeur inférieurs à 64bits?