func CopyFile(dstName, srcName string) (written int64, err os.Error) {
src, err := os.Open(srcName, os.O_RDONLY, 0)
if err != nil {
return
}
dst, err := os.Open(dstName, os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
return
}
written, err = io.Copy(dst, src)
dst.Close()
src.Close()
return
}
Le problème potentiel est que si le second appel à os.Open échoue, la fonction se terminera sans avoir fermé le fichier source. On peut y remédier en ajoutant un appel src.Close() avant la deuxième instruction de retour, mais si la fonction est bien plus complexe, il n'est pas dit que le développeur ait pensé à tous les cas de figure. L’instruction defer, nous permet de fermer les fichiers à tous les coups.
func CopyFile(dstName, srcName string) (written int64, err os.Error) {
src, err := os.Open(srcName, os.O_RDONLY, 0)
if err != nil {
return
}
defer src.Close()
dst, err := os.Open(dstName, os.O_WRONLY|os.O_CREATE, 0644)
if err != nil {
return
}
defer dst.Close()
return io.Copy(dst, src)
}
Quel que soit le nombre d’instructions return dans la fonction, l’instruction defer fermera tous les fichiers à la fin d'exécution de la fonction. Le comportement du defer est prédictible :
func a() {
i := 0
defer fmt.Println(i)
i++
return
}
func b() {
for i := 0; i < 4; i++ {
defer fmt.Print(i)
}
}
func c() (i int) {
defer func() {
i++
}()
return 1
}
func paniquons() {
defer func(s string) {
fmt.Println("Ce message sera affiché en dernier")
}()
fmt.Println("Ce message sera affiché en premier")
panic("Erreur")
fmt.Println("Ce message ne sera pas affiché")
}
package main
import "fmt"
func main() {
f()
fmt.Println("Retour normal de la fonction f.")
}
func f() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recover appelé dans la fonction f : ", r)
}
}()
fmt.Println("Appel de la fonction g.")
g(0)
fmt.Println("Retour normal de la fonction g.")
}
func g(i int) {
if i > 3 {
fmt.Println("Appel à panic")
panic(fmt.Sprintf("%v", i))
}
defer fmt.Println("Instruction retardée (defer) dans la fonction g : ", i)
fmt.Println("Affichage dans la fonction g : ", i)
g(i+1)
}
La fonction g reçoit en paramètre un entier i et panique si i est plus grand que 3, dans le cas contraire la fonction continue son exécution et s'appelle elle-même avec l’argument i+1.Appel de la fonction g. Affichage dans la fonction g : 0 Affichage dans la fonction g : 1 Affichage dans la fonction g : 2 Affichage dans la fonction g : 3 Appel à panic Instruction retardée (defer) dans la fonction g : 3 Instruction retardée (defer) dans la fonction g : 2 Instruction retardée (defer) dans la fonction g : 1 Instruction retardée (defer) dans la fonction g : 0 Recover appelé dans la fonction f : 4 Retour normal de la fonction f.Si nous supprimons l'appel à defer dans la fonction f, il n'y a aura pas de récupération (avec recover) et le programme sera terminé plus tôt (sans revenir dans la fonction main de notre exemple). Le programme modifié affichera :
Appel de la fonction g. Affichage dans la fonction g : 0 Affichage dans la fonction g : 1 Affichage dans la fonction g : 2 Affichage dans la fonction g : 3 Appel à panic Instruction retardée (defer) dans la fonction g : 3 Instruction retardée (defer) dans la fonction g : 2 Instruction retardée (defer) dans la fonction g : 1 Instruction retardée (defer) dans la fonction g : 0 panic: 4 panic PC=0x2a9cd8 [... suite de l'affichage de la pile]
Une traduction du blog officiel de golang expliquant le mécanisme de la réflexion en Go. Lire »
Préconisations officielles pour la gestion des erreurs dans un programme golang. Cet article complète les explications sur panic, defer et recover Lire »
Traduction d'une partie des spécifications officielles du langage go, cet article explique comment go gère la mémoire. Lire »
Traduction d'un article du blog officiel expliquant comment échanger des données entre deux programmes golang grâce à un format natif Lire »
Traduction d'une partie des spécifications officielles du langage Go, cet article explique comment développer en Go. Lire »
Soyez le premier à commenter cet article
Tous les commentaires sont soumis à modération. Les balises HTML sont pour la plupart autorisées. Les liens contextuels et intéressants sont en follow.