Обработване на грешки
21.10.2014
Могат ли да се наследяват типове?
По какво се различава синтаксисът за викане на метод върху обект и върху указател към обект?
За какво можем да използваме таговете на поле в struct
?
Marshal
и Unmarshal
Какво е метод? Могат ли да се добавят методи извън пакета, в който е дефиниран типът?
Как да накараме наш тип да имплементира интерфейс?
Дайте дефиниция на полиморфизъм, с три думи без да използвате чуждици!
error handling
errno
#include <stdio.h> #include <errno.h> #include <string.h> extern int errno; int main () { FILE* pf = fopen("unexist.txt", "rb"); if (pf == NULL) { fprintf(stderr, "Value of errno: %d\n", errno); perror("Error printed by perror"); fprintf(stderr, "Error opening file: %s\n", strerror(errno)); } else { fclose(pf); } return 0; }
Има грубо-казано 2 начина
type error interface { Error() string }
os.Open
връща os.PathError
:type PathError struct { Op string // "open", "unlink", etc. Path string // Файлът с грешката Err error // Грешката, върната от system call-a } func (e *PathError) Error() string { return e.Op + " " + e.Path + ": " + e.Err.Error() }
func CreateFile(filename string) { file, err = os.Create(filename) if err == nil { return } if e, ok := err.(*os.PathError); ok && e.Err == syscall.ENOSPC { deleteTempFiles() CreateFile(filename) } }
defer
добавя функцията, която сте подали, в един списък (стек)mutex-и
, etc)func CopyFile(dstName, srcName string) (written int64, err error) { src, err := os.Open(srcName) if err != nil { return } dst, err := os.Create(dstName) if err != nil { return } written, err = io.Copy(dst, src) dst.Close() src.Close() return }
func CopyFile(dstName, srcName string) (written int64, err error) { src, err := os.Open(srcName) if err != nil { return } defer src.Close() dst, err := os.Create(dstName) if err != nil { return } defer dst.Close() return io.Copy(dst, src) }
defer
statement-ите ни позволяват да мислим за затварянето на файловете веднага след отварянето имdefer
се оценяват, когато самият defer
statement се оценяваfunc a() { i := 0 defer fmt.Println(i) i++ return }
LIFO
редfunc b() { for i := 0; i < 4; i++ { defer fmt.Print(i) } }
defer
-натите функции могат да "пипат" по именованите връщани аргументи на обграждащата функцияfunc c() (i int) { defer func() { i++ }() return 1 }
package main
import (
"fmt"
)
func deferExample() { for i := 0; i < 5; i++ { defer func(i int) { fmt.Printf(" %v", i) }(i) } }
func main() {
deferExample()
}
-
package main
import (
"fmt"
)
func deferExample() { for i := 0; i < 5; i++ { defer func() { fmt.Printf(" %v", i) }() } }
func main() {
deferExample()
}
panic
е вградена функцияpanic
, изпълнението на F спира, всички `defer`-нати функции на F се изпълняват нормално, след което изпълнението се връща във функцията, извикала Fpanic
thread
) не свършат, когато програмата гърмиpanic
, както и след разни runtime грешки, като out-of-bounds array access
recover
е безполезен без defer
( може да се съвземете само в defer )recover
не прави нищо (връща nil
), ако текущата горутина не е в паникаrecover
връща аргумента, подаден на panic
func g(i int) { if i > 3 { fmt.Println("Panicking!") panic(fmt.Sprintf("%v", i)) } defer fmt.Println("Defer in g", i) fmt.Println("Printing in g", i) g(i + 1) }
func f() { defer func() { if r := recover(); r != nil { fmt.Println("Recovered in f", r) } }() fmt.Println("Calling g.") g(0) fmt.Println("Returned normally from g.") }
package main
import "fmt"
func main() { f() fmt.Println("Returned normally from f.") }
func f() {
defer func() {
if r := recover(); r != nil {
fmt.Println("Recovered in f", r)
}
}()
fmt.Println("Calling g.")
g(0)
fmt.Println("Returned normally from g.")
}
func g(i int) {
if i > 3 {
fmt.Println("Panicking!")
panic(fmt.Sprintf("%v", i))
}
defer fmt.Println("Defer in g", i)
fmt.Println("Printing in g", i)
g(i + 1)
}