рдЧреЛ рдореЗрдВ рдмрд┐рдирд╛ рдШрдмрд░рд╛рд╣рдЯ рдХреЗ рдирд╣реАрдВ

рд╣реЗрд▓реЛрдмреНрд░рд╛рд╣ рдХреЗ рдкреНрд░рд┐рдп рдкрд╛рдардХреЛрдВ, рдирдорд╕реНрдХрд╛рд░ред рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рд╕рдВрднрд╛рд╡рд┐рдд рдирдП рдбрд┐рдЬрд╛рдЗрди рдкрд░ рдЪрд░реНрдЪрд╛ рдХрд░рддреЗ рд╣реБрдП рдФрд░ рд╕реНрдкрд╖реНрдЯ рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рд▓рд╛рднреЛрдВ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдмрд╣рд╕ рдХрд░рддреЗ рд╣реБрдП, рдореИрдВрдиреЗ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреА рдХреБрдЫ рд╡рд┐рд╢реЗрд╖рддрд╛рдУрдВ, рдкреИрдирд┐рдХ рдФрд░ рдЧреЛ рдореЗрдВ рдЙрдирдХреА рд╡рд╕реВрд▓реА рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░рдиреЗ рдХрд╛ рдкреНрд░рд╕реНрддрд╛рд╡ рдХрд┐рдпрд╛ рд╣реИ рдЬреЛ рдЕрднреНрдпрд╛рд╕ рдореЗрдВ рдЙрдкрдпреЛрдЧреА рд╣реЛрдВрдЧреЗред
рдЫрд╡рд┐


рддреНрд░реБрдЯрд┐


рддреНрд░реБрдЯрд┐ рдПрдХ рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╣реИред рдФрд░ рдЧреЛ рдореЗрдВ рдЕрдзрд┐рдХрд╛рдВрд╢ рдЗрдВрдЯрд░рдлреЗрд╕ рдХреА рддрд░рд╣, рддреНрд░реБрдЯрд┐ рдХреА рдкрд░рд┐рднрд╛рд╖рд╛ рдЫреЛрдЯреА рдФрд░ рд╕рд░рд▓ рд╣реИ:


type error interface { Error() string } 

рдпрд╣ рдХрд┐рд╕реА рднреА рдкреНрд░рдХрд╛рд░ рдХреЛ рдмрджрд▓ рджреЗрддрд╛ рд╣реИ рдЬрд┐рд╕рдореЗрдВ рддреНрд░реБрдЯрд┐ рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рддреНрд░реБрдЯрд┐ рдХреЗ рд░реВрдк рдореЗрдВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЬреИрд╕рд╛ рдХрд┐ рд░реЙрдм рдкрд╛рдЗрдХ рдиреЗ рд╕рд┐рдЦрд╛рдпрд╛, рддреНрд░реБрдЯрд┐рдпрд╛рдВ рдореВрд▓реНрдп рд╣реИрдВ , рдФрд░ рд╡рд┐рднрд┐рдиреНрди рддрд░реНрдХ рдХреЛ рд╣реЗрд░рдлреЗрд░ рдХрд░рдиреЗ рдФрд░ рдкреНрд░реЛрдЧреНрд░рд╛рдо рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдореВрд▓реНрдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред


рдЧреЛ рдорд╛рдирдХ рдкреБрд╕реНрддрдХрд╛рд▓рдп рдореЗрдВ рджреЛ рдХрд╛рд░реНрдп рд╣реИрдВ рдЬреЛ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрд╕рд╛рдиреА рд╕реЗ рдЙрдкрдпреЛрдЧ рдХрд┐рдП рдЬрд╛рддреЗ рд╣реИрдВред рддреНрд░реБрдЯрд┐рдпрд╛рдБред рдирдпрд╛ рдлрд╝рдВрдХреНрд╢рди рд╕рд░рд▓ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЕрдЪреНрдЫреА рддрд░рд╣ рд╕реЗ рдЕрдиреБрдХреВрд▓ рд╣реИред Fmt.Errorf рдлрд╝рдВрдХреНрд╢рди рдорд╛рдирдХ рд╕реНрд╡рд░реВрдкрдг рдХреЗ рдЙрдкрдпреЛрдЧ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИред


 err := errors.New("emit macho dwarf: elf header corrupted") const name, id = "bimmler", 17 err := fmt.Errorf("user %q (id %d) not found", name, id) 

рдЖрдорддреМрд░ рдкрд░, рддреНрд░реБрдЯрд┐рдпреЛрдВ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЗ рд▓рд┐рдП рддреНрд░реБрдЯрд┐ рдкреНрд░рдХрд╛рд░ рдкрд░реНрдпрд╛рдкреНрдд рд╣реЛрддрд╛ рд╣реИред рд▓реЗрдХрд┐рди рдХрднреА-рдХрднреА рдПрдХ рддреНрд░реБрдЯрд┐ рдХреЗ рд╕рд╛рде рдЕрддрд┐рд░рд┐рдХреНрдд рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╕рд╛рд░рд┐рдд рдХрд░рдирд╛ рдЖрд╡рд╢реНрдпрдХ рд╣реЛ рд╕рдХрддрд╛ рд╣реИ; рдРрд╕реЗ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдЖрдк рдЕрдкрдиреА рдЦреБрдж рдХреА рдкреНрд░рдХрд╛рд░ рдХреА рддреНрд░реБрдЯрд┐ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред
рдПрдХ рдЕрдЪреНрдЫрд╛ рдЙрджрд╛рд╣рд░рдг рдУрдПрд╕ рдкреИрдХреЗрдЬ рд╕реЗ PathError рдХрд╛ рдкреНрд░рдХрд╛рд░ рд╣реИ


 // PathError records an error and the operation and file path that caused it. type PathError struct { Op string Path string Err error } func (e *PathError) Error() string { return e.Op + " " + e.Path + ": " + e.Err.Error() } 

рдРрд╕реА рддреНрд░реБрдЯрд┐ рдХреЗ рдореВрд▓реНрдп рдореЗрдВ рдСрдкрд░реЗрд╢рди, рдкрде рдФрд░ рддреНрд░реБрдЯрд┐ рд╢рд╛рдорд┐рд▓ рд╣реЛрдЧреАред


рд╡реЗ рдЗрд╕ рддрд░рд╣ рд╕реЗ рд╢реБрд░реВ рд╣реЛрддреЗ рд╣реИрдВ:


 ... return nil, &PathError{"open", name, syscall.ENOENT} ... return nil, &PathError{"close", file.name, e} 

рдкреНрд░рд╕рдВрд╕реНрдХрд░рдг рдХрд╛ рдПрдХ рдорд╛рдирдХ рд░реВрдк рд╣реЛ рд╕рдХрддрд╛ рд╣реИ:


 _, err := os.Open("---") if err != nil{ fmt.Println(err) } // open ---: The system cannot find the file specified. 

рд▓реЗрдХрд┐рди рдЕрдЧрд░ рдЕрддрд┐рд░рд┐рдХреНрдд рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдЖрдк * os.PathError рдореЗрдВ рддреНрд░реБрдЯрд┐ рдЕрдирдкреИрдХ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 _, err := os.Open("---") if pe, ok := err.(*os.PathError);ok{ fmt.Printf("Err: %s\n", pe.Err) fmt.Printf("Op: %s\n", pe.Op) fmt.Printf("Path: %s\n", pe.Path) } // Err: The system cannot find the file specified. // Op: open // Path: --- 

рдПрдХ рд╣реА рджреГрд╖реНрдЯрд┐рдХреЛрдг рд▓рд╛рдЧреВ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ рдпрджрд┐ рдлрд╝рдВрдХреНрд╢рди рдХрдИ рдЕрд▓рдЧ-рдЕрд▓рдЧ рдкреНрд░рдХрд╛рд░ рдХреА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░ рд╕рдХрддрд╛ рд╣реИред
рдЦреЗрд▓рдиреЗ


рдХрдИ рдкреНрд░рдХрд╛рд░ рдХреА рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреА рдШреЛрд╖рдгрд╛, рдкреНрд░рддреНрдпреЗрдХ рдХрд╛ рдЕрдкрдирд╛ рдбреЗрдЯрд╛ рд╣реИ:


рдХреЛрдб
 type ErrTimeout struct { Time time.Duration Err error } func (e *ErrTimeout) Error() string { return e.Time.String() + ": " + e.Err.Error() } type ErrPermission struct { Status string Err error } func (e *ErrPermission) Error() string { return e.Status + ": " + e.Err.Error() } 

рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдЬреЛ рдЗрди рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд╡рд╛рдкрд╕ рдХрд░ рд╕рдХрддрд╛ рд╣реИ:


рдХреЛрдб
 func proc(n int) error { if n <= 10 { return &ErrTimeout{Time: time.Second * 10, Err: errors.New("timeout error")} } else if n >= 10 { return &ErrPermission{Status: "access_denied", Err: errors.New("permission denied")} } return nil } 

рдЯрд╛рдЗрдк рдХрд╛рд╕реНрдЯреНрд╕ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдореЗрдВ рддреНрд░реБрдЯрд┐:


рдХреЛрдб
 func main(){ err := proc(11) if err != nil { switch e := err.(type) { case *ErrTimeout: fmt.Printf("Timeout: %s\n", e.Time.String()) fmt.Printf("Error: %s\n", e.Err) case *ErrPermission: fmt.Printf("Status: %s\n", e.Status) fmt.Printf("Error: %s\n", e.Err) default: fmt.Println("hm?") os.Exit(1) } } } 

рдЗрд╕ рдШрдЯрдирд╛ рдореЗрдВ рдХрд┐ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд╡рд┐рд╢реЗрд╖ рдЧреБрдгреЛрдВ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдкреИрдХреЗрдЬ рд╕реНрддрд░ рдкрд░ рддреНрд░реБрдЯрд┐рдпреЛрдВ рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЪрд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдЧреЛ рдореЗрдВ рдЕрдЪреНрдЫрд╛ рдЕрднреНрдпрд╛рд╕ рд╣реИред рдПрдХ рдЙрджрд╛рд╣рд░рдг io.EOF, io.ErrNoProgress, рдФрд░ рдЗрд╕реА рддрд░рд╣ рдХреА рддреНрд░реБрдЯрд┐рдпрд╛рдВ рд╣реИрдВред


рдиреАрдЪреЗ рджрд┐рдП рдЧрдП рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рд╣рдо рдкрдарди рдХреЛ рдмрд╛рдзрд┐рдд рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЬрдм рддреНрд░реБрдЯрд┐ io.EOF рд╣реЛрддреА рд╣реИ рддрдм рд╣рдо рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдЪрд▓рд╛рдирд╛ рдЬрд╛рд░реА рд░рдЦрддреЗ рд╣реИрдВ рдпрд╛ рд╣рдо рдХрд┐рд╕реА рдЕрдиреНрдп рддреНрд░реБрдЯрд┐ рдХреЗ рд▓рд┐рдП рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЛ рдмрдВрдж рдХрд░ рджреЗрддреЗ рд╣реИрдВред


 func main(){ reader := strings.NewReader("hello world") p := make([]byte, 2) for { _, err := reader.Read(p) if err != nil{ if err == io.EOF { break } log.Fatal(err) } } } 

рдпрд╣ рдкреНрд░рднрд╛рд╡реА рд╣реИ рдХреНрдпреЛрдВрдХрд┐ рддреНрд░реБрдЯрд┐рдпрд╛рдБ рдХреЗрд╡рд▓ рдПрдХ рдмрд╛рд░ рдЙрддреНрдкрдиреНрди рд╣реЛрддреА рд╣реИрдВ рдФрд░ рдкреБрди: рдЙрдкрдпреЛрдЧ рдХреА рдЬрд╛рддреА рд╣реИрдВред


рд╕реНрдЯреИрдХ рдЯреНрд░реЗрд╕


рд╕реНрдЯреИрдХ рдХреИрдкреНрдЪрд░ рдХреЗ рд╕рдордп рдмреБрд▓рд╛рдП рдЧрдП рдХрд╛рд░реНрдпреЛрдВ рдХреА рд╕реВрдЪреАред рд╕реНрдЯреИрдХ рдЯреНрд░реЗрд╕рд┐рдВрдЧ рдЖрдкрдХреЛ рд╕рд┐рд╕реНрдЯрдо рдореЗрдВ рдХреНрдпрд╛ рдЪрд▓ рд░рд╣рд╛ рд╣реИ рдЗрд╕рдХрд╛ рдПрдХ рдмреЗрд╣рддрд░ рд╡рд┐рдЪрд╛рд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИред рд▓реЙрдЧреНрд╕ рдореЗрдВ рдЯреНрд░реЗрд╕ рд╕рд╣реЗрдЬрдирд╛ рдбрд┐рдмрдЧрд┐рдВрдЧ рдХреЗ рд╕рдордп рдЧрдВрднреАрд░рддрд╛ рд╕реЗ рдорджрдж рдХрд░ рд╕рдХрддрд╛ рд╣реИред


рдЧреЛ рдореЗрдВ рдЕрдХреНрд╕рд░ рдЗрд╕ рдЬрд╛рдирдХрд╛рд░реА рдХреА рдХрдореА рд╣реЛрддреА рд╣реИ, рд▓реЗрдХрд┐рди рд╕реМрднрд╛рдЧреНрдп рд╕реЗ рдЧреЛ рдореЗрдВ рдбрдВрдк рд╣реЛрдирд╛ рдореБрд╢реНрдХрд┐рд▓ рдирд╣реАрдВ рд╣реИред


рдЖрдк рдорд╛рдирдХ рдЖрдЙрдЯрдкреБрдЯ рдкрд░ рдЯреНрд░реЗрд╕ рдХрд╛ рдЙрддреНрдкрд╛рджрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП debug.PrintStack () рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 func main(){ foo() } func foo(){ bar() } func bar(){ debug.PrintStack() } 

рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, Stderr рдХреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдЬрд╛рдирдХрд╛рд░реА рд▓рд┐рдЦреА рдЬрд╛рдПрдЧреА:


рдЕрдиреЗрдХрддрд╛
 goroutine 1 [running]: runtime/debug.Stack(0x1, 0x7, 0xc04207ff78) .../Go/src/runtime/debug/stack.go:24 +0xae runtime/debug.PrintStack() .../Go/src/runtime/debug/stack.go:16 +0x29 main.bar() .../main.go:13 +0x27 main.foo() .../main.go:10 +0x27 main.main() .../main.go:6 +0x27 

debug.Stack () рд╕реНрдЯреИрдХ рдбрдВрдк рдХреЗ рд╕рд╛рде рдмрд╛рдЗрдЯреНрд╕ рдХрд╛ рдПрдХ рдЯреБрдХрдбрд╝рд╛ рджреЗрддрд╛ рд╣реИ, рдЬрд┐рд╕реЗ рдмрд╛рдж рдореЗрдВ рд▓реЙрдЧ рдЗрди рдпрд╛ рдХрд╣реАрдВ рдФрд░ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред


 b := debug.Stack() fmt.Printf("Trace:\n %s\n", b) 

рдЕрдЧрд░ рд╣рдо рдРрд╕рд╛ рдХрд░рддреЗ рд╣реИрдВ рддреЛ рдПрдХ рдФрд░ рдмрд╛рдд рд╣реИ:


 go bar() 

рддрдм рд╣рдореЗрдВ рдЖрдЙрдЯрдкреБрдЯ рдкрд░ рдирд┐рдореНрди рдЬрд╛рдирдХрд╛рд░реА рдорд┐рд▓рддреА рд╣реИ:


 main.bar() .../main.go:19 +0x2d created by main.foo .../main.go:14 +0x3c 

рдкреНрд░рддреНрдпреЗрдХ рдЧреЛрд░реЛрдЗрди рдХрд╛ рдПрдХ рдЕрд▓рдЧ рдвреЗрд░ рд╣реЛрддрд╛ рд╣реИ, рдХреНрд░рдорд╢рдГ, рд╣рдореЗрдВ рдХреЗрд╡рд▓ рдЗрд╕рдХреА рдбрдВрдк рдорд┐рд▓рддреА рд╣реИред рд╡реИрд╕реЗ, рдЧреЛрд░реЛрдЗрдЯрд┐рди рдХреЗ рдЕрдкрдиреЗ рд╕реНрд╡рдпрдВ рдХреЗ рдвреЗрд░ рд╣реИрдВ, рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрддрд┐ рдЕрднреА рднреА рдЗрд╕ рд╕реЗ рдЬреБрдбрд╝реА рд╣реБрдИ рд╣реИ, рд▓реЗрдХрд┐рди рдмрд╛рдж рдореЗрдВ рдЙрд╕ рдкрд░ рдФрд░ рдЕрдзрд┐рдХред
рдФрд░ рдЗрд╕рд▓рд┐рдП, рд╕рднреА рдЧреЛрд░рдЖрдЙрдЯреНрд╕ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рджреЗрдЦрдиреЗ рдХреЗ рд▓рд┐рдП, рдЖрдк рд░рдирдЯрд╛рдЗрдо рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред рдЯреИрдХ () рдФрд░ рджреВрд╕рд░рд╛ рддрд░реНрдХ рд╕рд╣реА рдкрд╛рд╕ рдХрд░реЗрдВред


 func bar(){ buf := make([]byte, 1024) for { n := runtime.Stack(buf, true) if n < len(buf) { break } buf = make([]byte, 2*len(buf)) } fmt.Printf("Trace:\n %s\n", buf) } 

рдЕрдиреЗрдХрддрд╛
 Trace: goroutine 5 [running]: main.bar() .../main.go:21 +0xbc created by main.foo .../main.go:14 +0x3c goroutine 1 [sleep]: time.Sleep(0x77359400) .../Go/src/runtime/time.go:102 +0x17b main.foo() .../main.go:16 +0x49 main.main() .../main.go:10 +0x27 

рдЗрд╕ рдЬрд╛рдирдХрд╛рд░реА рдХреЛ рддреНрд░реБрдЯрд┐ рдореЗрдВ рдЬреЛрдбрд╝реЗрдВ рдФрд░ рдЗрд╕ рдкреНрд░рдХрд╛рд░ рдЗрд╕рдХреА рд╕реВрдЪрдирд╛ рд╕рд╛рдордЧреНрд░реА рдХреЛ рдмрдврд╝рд╛рдПрдБред
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдЗрд╕ рддрд░рд╣:


 type ErrStack struct { StackTrace []byte Err error } func (e *ErrStack) Error() string { var buf bytes.Buffer fmt.Fprintf(&buf, "Error:\n %s\n", e.Err) fmt.Fprintf(&buf, "Trace:\n %s\n", e.StackTrace) return buf.String() } 

рдЖрдк рдЗрд╕ рддреНрд░реБрдЯрд┐ рдХреЛ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВ:


 func NewErrStack(msg string) *ErrStack { buf := make([]byte, 1024) for { n := runtime.Stack(buf, true) if n < len(buf) { break } buf = make([]byte, 2*len(buf)) } return &ErrStack{StackTrace: buf, Err: errors.New(msg)} } 

рддреЛ рдЖрдк рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЗрд╕ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ:


 func main() { err := foo() if err != nil { fmt.Println(err) } } func foo() error{ return bar() } func bar() error{ err := NewErrStack("error") return err } 

рдЕрдиреЗрдХрддрд╛
 Error: error Trace: goroutine 1 [running]: main.NewErrStack(0x4c021f, 0x5, 0x4a92e0) .../main.go:41 +0xae main.bar(0xc04207ff38, 0xc04207ff78) .../main.go:24 +0x3d main.foo(0x0, 0x48ebff) .../main.go:21 +0x29 main.main() .../main.go:11 +0x29 

рддрджрдиреБрд╕рд╛рд░, рддреНрд░реБрдЯрд┐ рдФрд░ рдЯреНрд░реЗрд╕ рдХреЛ рд╡рд┐рднрд╛рдЬрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:


 func main(){ err := foo() if st, ok := err.(*ErrStack);ok{ fmt.Printf("Error:\n %s\n", st.Err) fmt.Printf("Trace:\n %s\n", st.StackTrace) } } 

рдФрд░ рдирд┐рд╢реНрдЪрд┐рдд рд░реВрдк рд╕реЗ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рддреИрдпрд╛рд░ рд╕рдорд╛рдзрд╛рди рд╣реИред рдЙрдирдореЗрдВ рд╕реЗ рдПрдХ https://github.com/pkg/errors рдкреИрдХреЗрдЬ рд╣реИред рдпрд╣ рдЖрдкрдХреЛ рдПрдХ рдирдИ рддреНрд░реБрдЯрд┐ рдмрдирд╛рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЬрд┐рд╕рдореЗрдВ рдкрд╣рд▓реЗ рд╕реЗ рд╣реА рдЯреНрд░реЗрд╕ рд╕реНрдЯреИрдХ рд╣реЛрдЧрд╛, рдФрд░ рдЖрдк рдореМрдЬреВрджрд╛ рддреНрд░реБрдЯрд┐ рдХреЗ рд▓рд┐рдП рдЯреНрд░реЗрд╕ рдФрд░ / рдпрд╛ рдЕрддрд┐рд░рд┐рдХреНрдд рд╕рдВрджреЗрд╢ рдЬреЛрдбрд╝ рд╕рдХрддреЗ рд╣реИрдВред рдкреНрд▓рд╕ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рдЖрдЙрдЯрдкреБрдЯ рд╕реНрд╡рд░реВрдкрдгред


 import ( "fmt" "github.com/pkg/errors" ) func main(){ err := foo() if err != nil { fmt.Printf("%+v", err) } } func foo() error{ err := bar() return errors.Wrap(err, "error2") } func bar() error{ return errors.New("error") } 

рдЕрдиреЗрдХрддрд╛
 error main.bar .../main.go:20 main.foo .../main.go:16 main.main .../main.go:9 runtime.main .../Go/src/runtime/proc.go:198 runtime.goexit .../Go/src/runtime/asm_amd64.s:2361 error2 main.foo .../main.go:17 main.main .../main.go:9 runtime.main .../Go/src/runtime/proc.go:198 runtime.goexit .../Go/src/runtime/asm_amd64.s:2361 

% v рдХреЗрд╡рд▓ рд╕рдВрджреЗрд╢ рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░реЗрдЧрд╛


 error2: error 

рдШрдмрд░рд╛рд╣рдЯ / рдЙрдмрд░рдирд╛


рдЖрддрдВрдХ (рдЙрд░реНрдл рджреБрд░реНрдШрдЯрдирд╛, рдЙрд░реНрдл тАЛтАЛрдЖрддрдВрдХ), рдПрдХ рдирд┐рдпрдо рдХреЗ рд░реВрдк рдореЗрдВ, рдЦрд░рд╛рдмреА рдХреА рдЙрдкрд╕реНрдерд┐рддрд┐ рдХрд╛ рд╕рдВрдХреЗрдд рджреЗрддрд╛ рд╣реИ, рдЬрд┐рд╕рдХреЗ рдХрд╛рд░рдг рд╕рд┐рд╕реНрдЯрдо (рдпрд╛ рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рд╕рдмрд╕рд┐рд╕реНрдЯрдо) рдХрд╛рд░реНрдп рдХрд░рдирд╛ рдЬрд╛рд░реА рдирд╣реАрдВ рд░рдЦ рд╕рдХрддрд╛ рд╣реИред рдпрджрд┐ рдШрдмрд░рд╛рд╣рдЯ рдХреЛ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдЧреЛ рд░рдирдЯрд╛рдЗрдо рд╕реНрдЯреИрдХ рдХреЛ рджреЗрдЦрддрд╛ рд╣реИ, рддреЛ рдЗрд╕рдХреЗ рд▓рд┐рдП рдПрдХ рд╣реИрдВрдбрд▓рд░ рдЦреЛрдЬрдиреЗ рдХреА рдХреЛрд╢рд┐рд╢ рдХрд░ рд░рд╣рд╛ рд╣реИред


рдЕрдкреНрд░рдорд╛рдгрд┐рдд рдкреИрдирд┐рдХ рдПрдкреНрд▓реАрдХреЗрд╢рди рдХреЛ рд╕рдорд╛рдкреНрдд рдХрд░ рджреЗрддрд╛ рд╣реИред рдпрд╣ рдореМрд▓рд┐рдХ рд░реВрдк рд╕реЗ рдЙрдиреНрд╣реЗрдВ рдЙрди рддреНрд░реБрдЯрд┐рдпреЛрдВ рд╕реЗ рдЕрд▓рдЧ рдХрд░рддрд╛ рд╣реИ рдЬреЛ рдЖрдкрдХреЛ рдЦреБрдж рдХреЛ рд╕рдВрд╕рд╛рдзрд┐рдд рдХрд░рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рдирд╣реАрдВ рджреЗрддреЗ рд╣реИрдВред


рдкреИрдирд┐рдХ рдлрдВрдХреНрд╢рди рдХреЙрд▓ рдкрд░ рдЖрдк рдХреЛрдИ рднреА рддрд░реНрдХ рдкрд╛рд╕ рдХрд░ рд╕рдХрддреЗ рд╣реИрдВред


 panic(v interface{}) 

рдпрд╣ рдЙрд╕ рдкреНрд░рдХрд╛рд░ рдХреА рдЧрдбрд╝рдмрдбрд╝реА рд╕реЗ рдШрдмрд░рд╛рдиреЗ рдореЗрдВ рд╕реБрд╡рд┐рдзрд╛рдЬрдирдХ рд╣реИ рдЬреЛ рд╡рд╕реВрд▓реА рдХреЛ рд╕рд░рд▓ рдмрдирд╛рддрд╛ рд╣реИ рдФрд░ рдбрд┐рдмрдЧрд┐рдВрдЧ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИред


 panic(errors.New("error")) 

рдЧреЛ рдореЗрдВ рдбрд┐рдЬрд╛рд╕реНрдЯрд░ рд░рд┐рдХрд╡рд░реА рдПрдХ рдбрд┐рдлрд░реЗрдВрдЯ рдлрдВрдХреНрд╢рди рдХреЙрд▓ рдЙрд░реНрдл рдбреЗрдлрд░ рдкрд░ рдЖрдзрд╛рд░рд┐рдд рд╣реИред рдЗрд╕ рддрд░рд╣ рдХреЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рдкреИрд░реЗрдВрдЯ рдлрд╝рдВрдХреНрд╢рди рд╕реЗ рд▓реМрдЯрдиреЗ рдкрд░ рдирд┐рд╖реНрдкрд╛рджрд┐рдд рд╣реЛрдиреЗ рдХреА рдЧрд╛рд░рдВрдЯреА рд╣реИред рдХрд╛рд░рдг рдЪрд╛рд╣реЗ рдЬреЛ рднреА рд╣реЛ - рд░рд┐рдЯрд░реНрди рд╕реНрдЯреЗрдЯрдореЗрдВрдЯ, рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЕрдВрдд рдпрд╛ рдШрдмрд░рд╛рд╣рдЯред


рдФрд░ рдЕрдм рд░рд┐рдХрд╡рд░реА рдлрд╝рдВрдХреНрд╢рди рджреБрд░реНрдШрдЯрдирд╛ рдХреЗ рдмрд╛рд░реЗ рдореЗрдВ рдЬрд╛рдирдХрд╛рд░реА рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ рдФрд░ рдХреЙрд▓ рд╕реНрдЯреИрдХ рдХреЗ рдЕрдирдЗрдВрдбрд┐рдВрдЧ рдХреЛ рд░реЛрдХрдирд╛ рд╕рдВрднрд╡ рдмрдирд╛рддрд╛ рд╣реИред
рдПрдХ рд╡рд┐рд╢рд┐рд╖реНрдЯ рдкреИрдирд┐рдХ рдХреЙрд▓ рдФрд░ рд╣реИрдВрдбрд▓рд░:


 func main(){ defer func() { if err := recover(); err != nil{ fmt.Printf("panic: %s", err) } }() foo() } func foo(){ panic(errors.New("error")) } 

рдпрджрд┐ рдХреЛрдИ рдШрдмрд░рд╛рд╣рдЯ рди рд╣реЛ рддреЛ рд░рд┐рдЯрд░реНрди рдЗрдВрдЯрд░рдлреЗрд╕ {} (рдЬрд┐рд╕реЗ рд╣рдо рдШрдмрд░рд╛рд╣рдЯ рдХреЗ рд▓рд┐рдП рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ) рдпрд╛ рд╢реВрдиреНрдп рдХрд░реЗрдВред


рдЖрдкрд╛рддрдХрд╛рд▓реАрди рд╣реИрдВрдбрд▓рд┐рдВрдЧ рдХреЗ рдПрдХ рдФрд░ рдЙрджрд╛рд╣рд░рдг рдкрд░ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВред рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдХреБрдЫ рдХрд╛рд░реНрдп рд╣реИрдВ рдЬрд┐рдирдХреЗ рд▓рд┐рдП рд╣рдо рдПрдХ рд╕рдВрд╕рд╛рдзрди рдХреЗ рд▓рд┐рдП рд╕реНрдерд╛рдирд╛рдВрддрд░рдг рдХрд░рддреЗ рд╣реИрдВ рдФрд░ рдЬреЛ рд╕рд┐рджреНрдзрд╛рдВрдд рдореЗрдВ, рдЖрддрдВрдХ рдкреИрджрд╛ рдХрд░ рд╕рдХрддрд╛ рд╣реИред


 func bar(f *os.File) { panic(errors.New("error")) } 

рд╕рдмрд╕реЗ рдкрд╣рд▓реЗ, рдЖрдкрдХреЛ рд╣рдореЗрд╢рд╛ рдЕрдВрдд рдореЗрдВ рдХреБрдЫ рдХреНрд░рд┐рдпрд╛рдПрдВ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛ рд╕рдХрддреА рд╣реИ, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рд╕рдВрд╕рд╛рдзрдиреЛрдВ рдХреА рд╕рдлрд╛рдИ, рд╣рдорд╛рд░реЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдлрд╝рд╛рдЗрд▓ рдХреЛ рдмрдВрдж рдХрд░рдирд╛ред


рджреВрд╕рд░реЗ, рдЗрд╕ рддрд░рд╣ рдХреЗ рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдЧрд▓рдд рдирд┐рд╖реНрдкрд╛рджрди рд╕реЗ рдкреВрд░реЗ рдХрд╛рд░реНрдпрдХреНрд░рдо рдХреА рд╕рдорд╛рдкреНрддрд┐ рдирд╣реАрдВ рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред


рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓, рдкреБрдирд░реНрдкреНрд░рд╛рдкреНрдд рдФрд░ рдмрдВрдж рдХрд░рдиреЗ рдХреЗ рд╕рд╛рде рд╣рд▓ рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИ:


 func foo()(err error) { file, _ := os.Open("file") defer func() { if r := recover(); r != nil { err = r.(error) //   ,   ,     // err := errors.New("trapped panic: %s (%T)", r, r) //     } file.Close() //   }() bar(file) return err } 

рд╕рдорд╛рдкрди рд╣рдореЗрдВ рдЙрдкрд░реЛрдХреНрдд рдШреЛрд╖рд┐рдд рдЪрд░ рдХреА рдУрд░ рдореБрдбрд╝рдиреЗ рдХреА рдЕрдиреБрдорддрд┐ рджреЗрддрд╛ рд╣реИ, рдЗрд╕рдХреЗ рд▓рд┐рдП рд╣рдо рдлрд╝рд╛рдЗрд▓ рдХреЛ рдмрдВрдж рдХрд░рдиреЗ рдХреА рдЧрд╛рд░рдВрдЯреА рджреЗрддреЗ рд╣реИрдВ рдФрд░ рджреБрд░реНрдШрдЯрдирд╛ рдХреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдЗрд╕рдореЗрдВ рд╕реЗ рдПрдХ рддреНрд░реБрдЯрд┐ рдирд┐рдХрд╛рд▓рддреЗ рд╣реИрдВ рдФрд░ рдЗрд╕реЗ рд╕рд╛рдорд╛рдиреНрдп рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд┐рдВрдЧ рддрдВрддреНрд░ рдХреЛ рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВред


рдРрд╕реА рд╡рд┐рдкрд░реАрдд рдкрд░рд┐рд╕реНрдерд┐рддрд┐рдпрд╛рдВ рд╣реЛрддреА рд╣реИрдВ рдЬрдм рдХреБрдЫ рддрд░реНрдХреЛрдВ рдХреЗ рд╕рд╛рде рдПрдХ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рд╣рдореЗрд╢рд╛ рд╕рд╣реА рддрд░реАрдХреЗ рд╕реЗ рдХрд╛рдо рдХрд░рдирд╛ рдЪрд╛рд╣рд┐рдП, рдФрд░ рдпрджрд┐ рдРрд╕рд╛ рдирд╣реАрдВ рд╣реЛрддрд╛ рд╣реИ, рддреЛ рдпрд╣ рд╡рд╛рд╕реНрддрд╡ рдореЗрдВ рдЦрд░рд╛рдм рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред


рдРрд╕реЗ рдорд╛рдорд▓реЛрдВ рдореЗрдВ, рдПрдХ рдЖрд╡рд░рдг рдлрд╝рдВрдХреНрд╢рди рдЬреЛрдбрд╝реЗрдВ рдЬрд┐рд╕рдореЗрдВ рд▓рдХреНрд╖реНрдп рдлрд╝рдВрдХреНрд╢рди рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИ, рдФрд░ рдПрдХ рддреНрд░реБрдЯрд┐ рдХреЗ рдорд╛рдорд▓реЗ рдореЗрдВ, рдЖрддрдВрдХ рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред


рдЬрд╛рдУ рдЖрдорддреМрд░ рдкрд░ рдЙрдкрд╕рд░реНрдЧ рд╣реЛрдирд╛ рдЪрд╛рд╣рд┐рдП :


 // MustCompile is like Compile but panics if the expression cannot be parsed. // It simplifies safe initialization of global variables holding compiled regular // expressions. func MustCompile(str string) *Regexp { regexp, error := Compile(str) if error != nil { panic(`regexp: Compile(` + quote(str) + `): ` + error.Error()) } return regexp } 

 // Must is a helper that wraps a call to a function returning (*Template, error) // and panics if the error is non-nil. It is intended for use in variable initializations // such as // var t = template.Must(template.New("name").Parse("html")) func Must(t *Template, err error) *Template { if err != nil { panic(err) } return t } 

рдпрд╣ рдШрдмрд░рд╛рд╣рдЯ рдФрд░ рдЧреЛрд░реЛрдЗрдЯрд┐рди рд╕реЗ рдЬреБрдбрд╝реА рдПрдХ рдФрд░ рдмрд╛рдд рдпрд╛рдж рд░рдЦрдиреЗ рд▓рд╛рдпрдХ рд╣реИред


рдКрдкрд░ рдЬреЛ рдЪрд░реНрдЪрд╛ рдХреА рдЧрдИ рдереА, рдЙрд╕рдореЗрдВ рд╕реЗ рдХреБрдЫ рдЕрдВрд╢:


  • рдкреНрд░рддреНрдпреЗрдХ рдЧреЛрд░реЗрдЗрди рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрд▓рдЧ рд╕реНрдЯреИрдХ рдЖрд╡рдВрдЯрд┐рдд рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред
  • рдШрдмрд░рд╛рд╣рдЯ рдХреЛ рдмреБрд▓рд╛рддреЗ рд╕рдордп, рд░рд┐рдХрд╡рд░реА рдХреЛ рд╕реНрдЯреИрдХ рдкрд░ рдЦреЛрдЬрд╛ рдЬрд╛рддрд╛ рд╣реИред
  • рдорд╛рдорд▓реЗ рдореЗрдВ рдЬрдм рдареАрдХ рдирд╣реАрдВ рдкрд╛рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рддреЛ рдкреВрд░рд╛ рдЖрд╡реЗрджрди рд╕рдорд╛рдкреНрдд рд╣реЛ рдЬрд╛рддрд╛ рд╣реИред

рдореБрдЦреНрдп рд╣реИрдВрдбрд▓рд░ рдлреВ рд╕реЗ рдЖрддрдВрдХ рдХреЛ рдирд╣реАрдВ рдкрдХрдбрд╝реЗрдВрдЧреЗ рдФрд░ рдХрд╛рд░реНрдпрдХреНрд░рдо рджреБрд░реНрдШрдЯрдирд╛рдЧреНрд░рд╕реНрдд рд╣реЛ рдЬрд╛рдПрдЧрд╛:


 func main(){ defer func() { if err := recover(); err != nil{ fmt.Printf("panic: %s", err) } }() go foo() time.Sleep(time.Minute) } func foo(){ panic(errors.New("error")) } 

рдпрд╣ рдПрдХ рд╕рдорд╕реНрдпрд╛ рд╣реЛрдЧреА рдпрджрд┐, рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рдПрдХ рд╣реИрдВрдбрд▓рд░ рдХреЛ рд╕рд░реНрд╡рд░ рд╕реЗ рдХрдиреЗрдХреНрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд╣рд╛ рдЬрд╛рддрд╛ рд╣реИред рдХрд┐рд╕реА рднреА рд╣реИрдВрдбрд▓рд░ рдореЗрдВ рднрдЧрджрдбрд╝ рдХреА рд╕реНрдерд┐рддрд┐ рдореЗрдВ, рдкреВрд░рд╛ рд╕рд░реНрд╡рд░ рдирд┐рд╖реНрдкрд╛рджрди рдХреЛ рдкреВрд░рд╛ рдХрд░реЗрдЧрд╛ред рдФрд░ рдЖрдк рдХрд┐рд╕реА рдХрд╛рд░рдг рд╕реЗ рдЗрди рдХрд╛рд░реНрдпреЛрдВ рдореЗрдВ рджреБрд░реНрдШрдЯрдирд╛рдУрдВ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдХреЛ рдирд┐рдпрдВрддреНрд░рд┐рдд рдирд╣реАрдВ рдХрд░ рд╕рдХрддреЗред
рдПрдХ рд╕рд╛рдзрд╛рд░рдг рдорд╛рдорд▓реЗ рдореЗрдВ, рд╕рдорд╛рдзрд╛рди рдХреБрдЫ рдЗрд╕ рддрд░рд╣ рджрд┐рдЦ рд╕рдХрддрд╛ рд╣реИ:


 type f func() func Def(fn f) { go func() { defer func() { if err := recover(); err != nil { log.Println("panic") } }() fn() }() } func main() { Def(foo) time.Sleep(time.Minute) } func foo() { panic(errors.New("error")) } 

рд╕рдВрднрд╛рд▓ / рдЬрд╛рдВрдЪ


рд╢рд╛рдпрдж рднрд╡рд┐рд╖реНрдп рдореЗрдВ рд╣рдо рддреНрд░реБрдЯрд┐ рд╕реЗ рдирд┐рдкрдЯрдиреЗ рдореЗрдВ рдмрджрд▓рд╛рд╡ рджреЗрдЦреЗрдВрдЧреЗред рдЖрдк рдЙрдирд╕реЗ рд▓рд┐рдВрдХ рдкрд░ рдкрд░рд┐рдЪрд┐рдд рд╣реЛ рд╕рдХрддреЗ рд╣реИрдВ:
go2draft
Go 2 рдореЗрдВ рддреНрд░реБрдЯрд┐ рд╣реИрдВрдбрд▓рд┐рдВрдЧ


рдЖрдЬ рдХреЗ рд▓рд┐рдП рдмрд╕ рдЗрддрдирд╛ рд╣реАред рдзрдиреНрдпрд╡рд╛рдж!

Source: https://habr.com/ru/post/hi422419/


All Articles