Обработване на грешки
21.10.2014
Могат ли да се наследяват типове?
По какво се различава синтаксисът за викане на метод върху обект и върху указател към обект?
За какво можем да използваме таговете на поле в struct?
Marshal и UnmarshalКакво е метод? Могат ли да се добавят методи извън пакета, в който е дефиниран типът?
Как да накараме наш тип да имплементира интерфейс?
Дайте дефиниция на полиморфизъм, с три думи без да използвате чуждици!
error handlingerrno#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 се изпълняват нормално, след което изпълнението се връща във функцията, извикала Fpanicthread) не свършат, когато програмата гърмиpanic, както и след разни runtime грешки, като out-of-bounds array access
recover е безполезен без defer ( може да се съвземете само в defer )recover не прави нищо (връща nil), ако текущата горутина не е в паникаrecover връща аргумента, подаден на panicfunc 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)
}