Allez les destructeurs?
Je sais il n'y a pas des destructeurs en Aller puisque, techniquement, il n'y a pas de classes. En tant que tel, j'utilise initClass
à effectuer les mêmes fonctions qu'un constructeur. Cependant, est-il un moyen de créer quelque chose pour imiter un destructeur en cas de résiliation d'un contrat, pour l'utilisation de, disons, la fermeture des fichiers? Maintenant je viens de l'appeler defer deinitClass
, mais ce n'est plus à du bidouillage, je pense, une mauvaise conception. Quelle serait la bonne façon?
- Un mineur en heads-up: le mot "classe" dans le nom d'un "constructeur" et "destructeur" fonctions est source de confusion et peut indiquer que vous maintenir un peu de mal modèle mental sur ce genre de choses: de telles fonctions initialiser/deinitialize les instances d'un type (eh bien, Allez, n'a pas de classes, mais les classes en C++comme les PLs sont des types), c'est du béton, les variables qui ont un type particulier. Ils n'ont pas initialiser/deinitialize un type lui-même. C'est pourquoi "constructeur" les fonctions sont généralement appelés
New()
ouNewWhatever()
en Aller: ils vous donnent un nouveau initialisé la valeur. - Vous pouvez trouver ceci pour être d'un intérêt particulier à l'égard de nommage des packages, des types et des fonctions écrits en Aller de code. Veillez également à consulter la section intitulée "Autres lectures" il.
- l'utilisation de initClass et deinitClass étaient juste générique, j'étais juste en utilisant les noms de montrer ce que je faisais. J'ai créé une structure (struct) alors appelé initStructName de faire quelques choses de fantaisie alors sous que j'ai ajouté reporter deinitStructName, à fermer des fichiers, et bien nettoyer etc.
- merci pour le lien
Vous devez vous connecter pour publier un commentaire.
Dans le feu de l'écosystème, il existe un omniprésente idiome pour traiter les objets qui s'enroulent précieux (et/ou externe) des ressources: une méthode spéciale désignée pour la libération de la ressource, appelée explicitement — généralement par l'intermédiaire de la
defer
mécanisme.Cette méthode particulière est généralement nommé
Close()
, et l'utilisateur de l'objet a à l'appeler explicitement quand ils sont fait avec les ressources de l'objet représente. Leio
paquet standard ne disposent même d'une interface spéciale,io.Plus près
, déclarant que la seule méthode. Les objets de mise en œuvre de I/O sur les différentes ressources telles que les sockets TCP, UDP points de terminaison et les fichiers de tous les satisfaireio.Closer
, et devraient être explicitementClose
d après utilisation.Appel d'une telle méthode de nettoyage est généralement effectuée par le
defer
mécanisme qui garantit la méthode de courir, peu importe si un bout de code qui s'exécute après l'acquisition de ressources serapanic()
ou pas.Vous remarquerez que de ne pas avoir implicite "destructeurs" tout à fait les soldes ne pas avoir implicite "constructeurs" en Aller. En fait, cela n'a rien à voir avec ne pas avoir de "classes" dans le jeu de Go: la langue concepteurs juste éviter magie autant que possible.
Note qui Vont de l'approche à ce problème pourrait apparaissent être un peu rudimentaire, mais en fait c'est la seule solution viable pour le moteur d'exécution mettant en vedette de garbage collection. Dans un langage à objets, mais sans GC, par exemple, C++, la destruction d'un objet bien défini, parce que la destruction d'un objet, soit quand elle est hors de portée ou lorsque
delete
est appelé sur son bloc de mémoire. Dans l'exécution de la cg, l'objet sera détruit à certains surtout point indéterminé dans le futur par le GC d'analyse, et ne peut pas être détruit. Donc, si l'objet encapsule certains ressource précieuse, que les ressources pourraient ne pas être réutilisé à tous, comme cela a été bien expliqué par @twotwotwo dans leur réponse.Un autre aspect intéressant à considérer est que le Go GC est entièrement concurrente (le programme régulier de l'exécution). Cela signifie qu'un GC fil qui est sur le point de recueillir un objet mort peut (et sera) pas le fil(s) qui a exécuté le code de cet objet quand il était vivant. À son tour, cela signifie que si le Go des types ont des destructeurs ensuite, le programmeur devra assurez-vous que le code que le destructeur s'exécute est correctement synchronisé avec le reste du programme—si l'état de l'objet affecte certaines structures de données externes. En fait, cela pourrait forcer le programmeur d'ajouter une telle synchronisation, même si l'objet n'en a pas besoin pour son fonctionnement normal (et la plupart des objets tombent dans cette catégorie). Et pensez à ce qui arrive à ceux exernal données strucrures qui est arrivé à être détruit avant le destructeur de l'objet a été appelé (le GC recueille des objets morts dans un non-déterministe façon). En d'autres termes, il est beaucoup plus facile à contrôler — et à raison — destruction des objets lorsqu'il est explicitement codé dans le programme de l'écoulement: à la fois pour déterminer si l'objet doit être détruit, et pour en garantir la bonne commande de sa destruction à l'égard de détruire des structures de données externes.
Si vous êtes familier avec .NET, il traite avec les ressources de nettoyage d'une manière qui ressemble à celui de l'Aller assez près: vos objets qui emballe des ressources précieuses qui ont à mettre en œuvre les
IDisposable
interface, et une méthode,Dispose()
, exportées par cette interface, doit être appelée explicitement lorsque vous avez terminé avec un tel objet. C# fournit certaines sucre syntaxique pour ce cas d'utilisation via leusing
déclaration qui en fait le compilateur organiser pour appelerDispose()
sur l'objet quand elle est hors de la portée déclarée par la déclaration de confidentialité. Allez, vous serez généralementdefer
des appels à des méthodes de nettoyage.Une note plus de prudence. Allez vous veut pour traiter les erreurs très au sérieux (contrairement à la plupart des grands langage de programmation avec leurs "il suffit de jeter une exception et ne pas donner un fsck sur ce qui se passe à cause de ça d'ailleurs, et dans quel état le programme sera en" attitude) et de sorte que vous pourriez envisager de contrôle d'erreur renvoie d'au moins certains des appels à des méthodes de nettoyage.
Un bon exemple est le cas de la
os.File
type de représentant de fichiers sur un système de fichiers. Le plaisir des choses est que l'appel àClose()
sur un fichier ouvert pourrait échouer pour des raisons légitimes, et si vous avez été écrit à ce fichier, cela peut indiquer que toutes les données que vous avez écrit à ce fichier avait atterri dans ce sur le système de fichiers. Pour plus de renseignements, veuillez lire la section "Notes" dans leclose(2)
manuel.En d'autres termes, il suffit de faire quelque chose comme
est ok pour les fichiers en lecture seule dans 99,9% des cas, mais pour l'ouverture des fichiers pour l'écriture, vous pourriez vouloir mettre en œuvre plus impliqués vérification d'erreur et une stratégie pour traiter avec eux (simple déclaration, attendez-puis-retry, demandez-alors-peut-être réessayer ou quoi que ce soit).
de l'exécution.SetFinalizer(ptr, finalizerFunc)
définit un finaliseur--pas un destructeur mais un autre mécanisme pour peut-être éventuellement libérer des ressources. Lire la documentation pour plus de détails, y compris les inconvénients. Ils peuvent ne pas s'exécuter jusqu'à ce que longtemps après que l'objet est en fait inaccessible, et ils pourraient ne pas fonctionner si le programme sort en premier. Ils ont également retarder la libération de la mémoire pour un autre cycle de GC.Si vous êtes l'acquisition de certains ressource limitée, qui n'en a pas déjà un outil de finalisation, et le programme finit par être incapable de continuer si elle a gardé une fuite, vous devez envisager de définir un outil de finalisation. Elle peut atténuer les fuites. Inaccessible fichiers et les connexions réseau sont déjà nettoyé par les finaliseurs dans la stdlib, ce n'est donc que d'autres types de ressources où personnalisés peuvent être utiles. Le plus évident est la classe de ressources système vous acquérir par le biais de
syscall
oucgo
, mais je peux imaginer d'autres.Alors qu'ils peuvent colmater quelques erreurs, vous ne devriez pas compter sur les finaliseurs. Ils ne fonctionnent pas jusqu'à ce que le GC ne. Parce que le programme pourrait sortir avant la prochaine GC, vous ne pouvez pas compter sur eux pour les choses qui doit être fait, comme le rinçage en tampon de sortie pour le système de fichiers. En supposant GC ne se produire, il pourrait ne pas arriver assez tôt: si un finaliseur est responsable de la fermeture des connexions réseau, peut-être un hôte distant atteint sa limite de connexions ouvertes pour vous avant de GC ou de votre processus atteint son fichier de descripteur de limite, ou vous manquez de les ports éphémères, ou quelque chose d'autre. Il est donc beaucoup mieux pour
defer
et faire le nettoyage de droit quand c'est nécessaire que d'utiliser un outil de finalisation et de l'espoir c'est fait assez vite.Vous ne voyez pas beaucoup de
SetFinalizer
appels dans le quotidien de la programmation Go, en partie parce que les plus importants sont dans la bibliothèque standard, et surtout à cause de leur gamme limitée de l'applicabilité en général.En bref, les finaliseurs pouvez nous aider en les libérant oublié de ressources dans les programmes de longue date, mais parce que pas beaucoup au sujet de leur comportement est garanti, ils ne sont pas digne d'être votre ressource principale-mécanisme de gestion.
SetFinalizer
est la seule méthode disponible pour gratuit cgo ressources en ligne lors de leur golang dépendances sont des ordures collectées - il est très utile pour c wrappers, en particulier lors de la C des objets ont des restrictions sur quand ils peuvent être libérés par rapport à une autre. Ce doit être la accepté de répondre.Il y a des Finaliseurs en Aller. J'ai écrit il y a peu post de blog à ce sujet. Ils ont même utilisé pour la fermeture des fichiers dans la bibliothèque standard comme vous pouvez le voir ici.
Cependant, je pense que l'utilisation d'reporter est plus préférable, car il est plus lisible et moins magique.
defer
et de libérer les ressources immédiatement que de s'appuyer sur des outils de finalisation. En d'autres termes, les finaliseurs pourrait être utile à une police d'assurance contre les autres-dur-à-brancher les fuites, mais ils ne sont pas bons en tant que votre principale ressource mécanisme de gestion.