learning_go/go-code-samples/awesomeProject/error-handling/main.go
2025-12-20 10:21:45 +03:00

92 lines
2.5 KiB
Go

package main
import (
"errors"
"io/fs"
"log"
)
func main() {
log.SetFlags(0) // no time stamp
// Read a single file
log.SetPrefix("Reading a single file: ")
_, err := ReadFile("no/file")
if err != nil {
log.Println("err = ", err)
}
// Unwrap the error returned by os.Open()
log.Println("errors.Unwrap(err) = ", errors.Unwrap(err))
// Confirm that the error is, or wraps, an fs.ErrNotExist error
log.Println("err is fs.ErrNotExist:", errors.Is(err, fs.ErrNotExist))
// Confirm that the error is, or wraps, an fs.PathError.
// errors.As() assigns the unwrapped PathError to target.
// This allows reading PathError's Path field.
target := &fs.PathError{}
if errors.As(err, &target) {
log.Printf("err as PathError: path is '%s'\n", target.Path)
log.Printf("err as PathError: op is '%s'\n", target.Op)
}
// Read files concurrently - handling context errors
log.SetPrefix("Reading files concurrently: ")
_, err = ReadFilesConcurrently([]string{"no/file/a", "no/file/b", "no/file/c"})
log.Println("err = ", err)
// Read multiple files
log.SetPrefix("Reading multiple files: ")
// Passing an empty slice triggers a plain error
_, err = ReadFiles([]string{})
log.Println("err = ", err)
// Passing multiple paths of non-existing files triggers a joined error
_, err = ReadFiles([]string{"no/file/a", "no/file/b", "no/file/c"})
log.Println("joined errors = ", err)
// Unwrap the errors inside the joined error
// A joined error does not have the method "func Unwrap() error"
// because it does not wrap a single error but rather a slice of errors.
// Therefore, errors.Unwrap() cannot unwrap the errors and returns nil.
log.Println("errors.Unwrap(err) = ", errors.Unwrap(err))
// To unwrap a joined error, you can type-assert that err has
// an Unwrap() method that returns a slice of errors.
e, ok := err.(interface{ Unwrap() []error })
if ok {
log.Println("e.Unwrap() = ", e.Unwrap())
}
// Network errors
log.SetPrefix("Network errors: ")
err = connectToTCPServer()
log.Println("err = ", err)
// Recover from a panic
log.SetPrefix("Recovering from a panic: ")
// This example is at the end of main, because the panic
// causes main to exit. Only the deferred function is
// called before exiting.
defer func() {
// Is this func invoked from a panic?
if r := recover(); r != nil {
// Yes: recover from the panic
log.Printf("isValidPath panicked: error is '%v'\n", r)
// ...
}
}()
// isValidPath panics because of an invalid regexp.
if isValidPath("/path/to/file") {
_, _ = ReadFile("/path/to/file")
}
}