Исходники и презентации
This commit is contained in:
15
lessons/errors/change_global_error/main.go
Normal file
15
lessons/errors/change_global_error/main.go
Normal file
@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Println("io.EOF == io.EOF:", io.EOF == io.EOF)
|
||||
previousErr := io.EOF
|
||||
|
||||
io.EOF = fmt.Errorf("changed error")
|
||||
fmt.Println("io.EOF == io.EOF:", io.EOF == io.EOF)
|
||||
fmt.Println("previousErr == io.EOF:", previousErr == io.EOF)
|
||||
}
|
||||
29
lessons/errors/constant_error/main.go
Normal file
29
lessons/errors/constant_error/main.go
Normal file
@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
|
||||
type Error string
|
||||
|
||||
func (e Error) Error() string {
|
||||
return string(e)
|
||||
}
|
||||
|
||||
const ErrEOF = Error("EOF")
|
||||
|
||||
func main() {
|
||||
var err error = ErrEOF
|
||||
err = io.EOF
|
||||
_ = err
|
||||
|
||||
// ErrEOF = Error("new error") -> coplilation error
|
||||
|
||||
anotherErrEOF1 := Error("EOF")
|
||||
fmt.Println(`anotherErrEOF1 = Error("EOF"):`, anotherErrEOF1 == ErrEOF)
|
||||
|
||||
anotherErrEOF2 := errors.New("EOF")
|
||||
fmt.Println("anotherErrEOF2 = io.EOF:", anotherErrEOF2 == io.EOF)
|
||||
}
|
||||
15
lessons/errors/division_by_zero/main.go
Normal file
15
lessons/errors/division_by_zero/main.go
Normal file
@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func divide(lhs, rhs int) {
|
||||
defer func() {
|
||||
fmt.Println("recovered:", recover())
|
||||
}()
|
||||
|
||||
_ = lhs / rhs
|
||||
}
|
||||
|
||||
func main() {
|
||||
divide(1000, 0)
|
||||
}
|
||||
12
lessons/errors/division_by_zero_float/main.go
Normal file
12
lessons/errors/division_by_zero_float/main.go
Normal file
@ -0,0 +1,12 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func divide(lhs, rhs float32) float32 {
|
||||
return lhs / rhs
|
||||
}
|
||||
|
||||
func main() {
|
||||
result := divide(1000, 0)
|
||||
fmt.Println(result)
|
||||
}
|
||||
32
lessons/errors/errno/main.go
Normal file
32
lessons/errors/errno/main.go
Normal file
@ -0,0 +1,32 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
const (
|
||||
OkStatus = iota
|
||||
EvenNumberErr
|
||||
ZeroNumberErr
|
||||
)
|
||||
|
||||
var Errno = OkStatus
|
||||
|
||||
func divide(lhs, rhs int) int {
|
||||
if rhs == 0 {
|
||||
Errno = ZeroNumberErr
|
||||
return 0
|
||||
} else if lhs%2 == 0 || rhs%2 == 0 {
|
||||
Errno = EvenNumberErr
|
||||
return 0
|
||||
}
|
||||
|
||||
Errno = OkStatus
|
||||
return lhs / rhs
|
||||
}
|
||||
|
||||
func main() {
|
||||
x := 100
|
||||
y := 0
|
||||
|
||||
value := divide(x, y)
|
||||
fmt.Println(value, Errno)
|
||||
}
|
||||
51
lessons/errors/error/main.go
Normal file
51
lessons/errors/error/main.go
Normal file
@ -0,0 +1,51 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type error interface {
|
||||
Error() string
|
||||
}
|
||||
|
||||
type DivisionError struct {
|
||||
errMessage string
|
||||
firstArgument int
|
||||
secondArgument int
|
||||
}
|
||||
|
||||
func NewDivisionError(message string, lhs, rhs int) DivisionError {
|
||||
return DivisionError{
|
||||
errMessage: message,
|
||||
firstArgument: lhs,
|
||||
secondArgument: rhs,
|
||||
}
|
||||
}
|
||||
|
||||
func (e DivisionError) Error() string {
|
||||
if e.errMessage != "" {
|
||||
return e.errMessage + " [" + strconv.Itoa(e.firstArgument) + ", " + strconv.Itoa(e.secondArgument) + "]"
|
||||
} else {
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
func divide(lhs, rhs int) (int, error) {
|
||||
if rhs == 0 {
|
||||
return 0, NewDivisionError("zero number", lhs, rhs)
|
||||
} else if lhs%2 == 0 || rhs%2 == 0 {
|
||||
return 0, NewDivisionError("even number", lhs, rhs)
|
||||
}
|
||||
|
||||
return lhs / rhs, nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
x := 100
|
||||
y := 0
|
||||
|
||||
value, err := divide(x, y)
|
||||
fmt.Println(value)
|
||||
fmt.Println(err)
|
||||
}
|
||||
36
lessons/errors/error_behavior/main.go
Normal file
36
lessons/errors/error_behavior/main.go
Normal file
@ -0,0 +1,36 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type ErrorFromAnotherPackage struct{}
|
||||
|
||||
func (e ErrorFromAnotherPackage) Error() string {
|
||||
return "error"
|
||||
}
|
||||
|
||||
func (e ErrorFromAnotherPackage) Path() string {
|
||||
return "path"
|
||||
}
|
||||
|
||||
type FSError interface {
|
||||
Path() string
|
||||
}
|
||||
|
||||
func IsFSError(err error) bool {
|
||||
_, ok := err.(FSError)
|
||||
return ok
|
||||
}
|
||||
|
||||
func getErrorFromAnotherPackage() error {
|
||||
return ErrorFromAnotherPackage{}
|
||||
//return fmt.Errorf("%w", ErrorFromAnotherPackage{})
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := getErrorFromAnotherPackage()
|
||||
if IsFSError(err) {
|
||||
fmt.Println("FSError")
|
||||
}
|
||||
}
|
||||
32
lessons/errors/error_flag/main.go
Normal file
32
lessons/errors/error_flag/main.go
Normal file
@ -0,0 +1,32 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func divideV1(lhs, rhs int) (int, bool) {
|
||||
if rhs == 0 {
|
||||
return 0, false
|
||||
}
|
||||
|
||||
return lhs / rhs, true
|
||||
}
|
||||
|
||||
func divideV2(lhs, rhs int, status *bool) int {
|
||||
*status = false
|
||||
if rhs == 0 {
|
||||
return 0
|
||||
}
|
||||
|
||||
*status = true
|
||||
return lhs / rhs
|
||||
}
|
||||
|
||||
func main() {
|
||||
x := 100
|
||||
y := 0
|
||||
|
||||
value, ok := divideV1(x, y)
|
||||
fmt.Println(value, ok)
|
||||
|
||||
value = divideV2(x, y, &ok)
|
||||
fmt.Println(value, ok)
|
||||
}
|
||||
21
lessons/errors/error_from_defer/main.go
Normal file
21
lessons/errors/error_from_defer/main.go
Normal file
@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
import "database/sql"
|
||||
|
||||
func getBalance(database *sql.DB, clientId int) (balance float32, err error) {
|
||||
query := "..."
|
||||
var rows *sql.Rows
|
||||
rows, err = database.Query(query, clientId)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
if err == nil {
|
||||
err = rows.Close()
|
||||
}
|
||||
}()
|
||||
|
||||
// reading...
|
||||
return balance, err
|
||||
}
|
||||
19
lessons/errors/error_new/main.go
Normal file
19
lessons/errors/error_new/main.go
Normal file
@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func createErrV1() error {
|
||||
return errors.New("simple error")
|
||||
}
|
||||
|
||||
func createErrV2() error {
|
||||
return fmt.Errorf("error with argument %d", 1000)
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println(createErrV1().Error())
|
||||
fmt.Println(createErrV2().Error())
|
||||
}
|
||||
43
lessons/errors/error_status/main.go
Normal file
43
lessons/errors/error_status/main.go
Normal file
@ -0,0 +1,43 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
const (
|
||||
OkStatus = iota
|
||||
EvenNumberErr
|
||||
ZeroNumberErr
|
||||
)
|
||||
|
||||
func divideV1(lhs, rhs int) (int, int) {
|
||||
if rhs == 0 {
|
||||
return 0, ZeroNumberErr
|
||||
} else if lhs%2 == 0 || rhs%2 == 0 {
|
||||
return 0, EvenNumberErr
|
||||
}
|
||||
|
||||
return lhs / rhs, OkStatus
|
||||
}
|
||||
|
||||
func divideV2(lhs, rhs int, status *int) int {
|
||||
if rhs == 0 {
|
||||
*status = ZeroNumberErr
|
||||
return 0
|
||||
} else if lhs%2 == 0 || rhs%2 == 0 {
|
||||
*status = EvenNumberErr
|
||||
return 0
|
||||
}
|
||||
|
||||
*status = OkStatus
|
||||
return lhs / rhs
|
||||
}
|
||||
|
||||
func main() {
|
||||
x := 100
|
||||
y := 0
|
||||
|
||||
value, status := divideV1(x, y)
|
||||
fmt.Println(value, status)
|
||||
|
||||
value = divideV2(x, y, &status)
|
||||
fmt.Println(value, status)
|
||||
}
|
||||
19
lessons/errors/error_with_stacktrace/main.go
Normal file
19
lessons/errors/error_with_stacktrace/main.go
Normal file
@ -0,0 +1,19 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
func main() {
|
||||
value, err := DoSomething()
|
||||
if err != nil {
|
||||
fmt.Printf("%+v", err)
|
||||
}
|
||||
fmt.Println(value)
|
||||
}
|
||||
|
||||
func DoSomething() (string, error) {
|
||||
return "", errors.New("some error explanation here")
|
||||
}
|
||||
14
lessons/errors/errorf/main.go
Normal file
14
lessons/errors/errorf/main.go
Normal file
@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := errors.New("source error")
|
||||
err = fmt.Errorf("additional error information: %v", err)
|
||||
|
||||
fmt.Println(err.Error())
|
||||
fmt.Println(errors.Unwrap(err))
|
||||
}
|
||||
17
lessons/errors/errorf_with_packing/main.go
Normal file
17
lessons/errors/errorf_with_packing/main.go
Normal file
@ -0,0 +1,17 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err := errors.New("source error")
|
||||
err = fmt.Errorf("additional error information: %w", err)
|
||||
err = fmt.Errorf("internal error: %w", err)
|
||||
|
||||
fmt.Println(err.Error())
|
||||
fmt.Println(errors.Unwrap(err))
|
||||
fmt.Println(errors.Unwrap(errors.Unwrap(err)))
|
||||
fmt.Println(errors.Unwrap(errors.Unwrap(errors.Unwrap(err))))
|
||||
}
|
||||
25
lessons/errors/errors_as/main.go
Normal file
25
lessons/errors/errors_as/main.go
Normal file
@ -0,0 +1,25 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type DatabaseError struct{}
|
||||
|
||||
func (d DatabaseError) Error() string {
|
||||
return "database error"
|
||||
}
|
||||
|
||||
func GetDataFromDB() error {
|
||||
return fmt.Errorf("failed to get data: %w", DatabaseError{})
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := GetDataFromDB()
|
||||
if errors.As(err, &DatabaseError{}) {
|
||||
fmt.Println(err.Error())
|
||||
} else {
|
||||
fmt.Println("unknown error")
|
||||
}
|
||||
}
|
||||
18
lessons/errors/errors_defer_ignoring/main.go
Normal file
18
lessons/errors/errors_defer_ignoring/main.go
Normal file
@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import "database/sql"
|
||||
|
||||
// Need to show solution
|
||||
|
||||
func getBalance(database *sql.DB, clientId int) (float32, error) {
|
||||
query := "..."
|
||||
rows, err := database.Query(query, clientId)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
defer rows.Close()
|
||||
|
||||
// reading...
|
||||
return 0., nil
|
||||
}
|
||||
16
lessons/errors/errors_handling/main.go
Normal file
16
lessons/errors/errors_handling/main.go
Normal file
@ -0,0 +1,16 @@
|
||||
package main
|
||||
|
||||
import "net/http"
|
||||
|
||||
// Need to show solution
|
||||
|
||||
func authentificate(*http.Request) error
|
||||
|
||||
func Authentificate(request *http.Request) error {
|
||||
err := authentificate(request)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
13
lessons/errors/errors_ignoring/main.go
Normal file
13
lessons/errors/errors_ignoring/main.go
Normal file
@ -0,0 +1,13 @@
|
||||
package main
|
||||
|
||||
import "errors"
|
||||
|
||||
// Need to show solution
|
||||
|
||||
func process() error {
|
||||
return errors.New("error")
|
||||
}
|
||||
|
||||
func main() {
|
||||
process()
|
||||
}
|
||||
21
lessons/errors/errors_is/main.go
Normal file
21
lessons/errors/errors_is/main.go
Normal file
@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var ErrDatabaseProblem = errors.New("database problem")
|
||||
|
||||
func GetDataFromDB() error {
|
||||
return fmt.Errorf("failed to get data: %w", ErrDatabaseProblem)
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := GetDataFromDB()
|
||||
if errors.Is(err, ErrDatabaseProblem) {
|
||||
fmt.Println(err.Error())
|
||||
} else {
|
||||
fmt.Println("unknown error")
|
||||
}
|
||||
}
|
||||
24
lessons/errors/errors_performance/performance_test.go
Normal file
24
lessons/errors/errors_performance/performance_test.go
Normal file
@ -0,0 +1,24 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"testing"
|
||||
|
||||
othererrors "github.com/pkg/errors"
|
||||
)
|
||||
|
||||
// go test -bench=. performance_test.go
|
||||
|
||||
var err error
|
||||
|
||||
func BenchmarkErrorWithoutStackTrace(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
err = errors.New("error")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkErrorWithStackTrace(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
err = othererrors.New("error")
|
||||
}
|
||||
}
|
||||
26
lessons/errors/errors_type_checking/main.go
Normal file
26
lessons/errors/errors_type_checking/main.go
Normal file
@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
type DatabaseError struct{}
|
||||
|
||||
func (d DatabaseError) Error() string {
|
||||
return "database error"
|
||||
}
|
||||
|
||||
func GetDataFromDB() error {
|
||||
return fmt.Errorf("failed to get data: %w", DatabaseError{})
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := GetDataFromDB()
|
||||
switch err := err.(type) {
|
||||
case DatabaseError:
|
||||
fmt.Println(err.Error())
|
||||
default:
|
||||
fmt.Println("unknown error")
|
||||
}
|
||||
|
||||
}
|
||||
21
lessons/errors/errors_value_checking/main.go
Normal file
21
lessons/errors/errors_value_checking/main.go
Normal file
@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
var ErrDatabaseProblem = errors.New("database problem")
|
||||
|
||||
func GetDataFromDB() error {
|
||||
return fmt.Errorf("failed to get data: %w", ErrDatabaseProblem)
|
||||
}
|
||||
|
||||
func main() {
|
||||
err := GetDataFromDB()
|
||||
if err == ErrDatabaseProblem {
|
||||
fmt.Println(err.Error())
|
||||
} else if err != nil {
|
||||
fmt.Println("unknown error")
|
||||
}
|
||||
}
|
||||
20
lessons/errors/incorrect_wrapping/main.go
Normal file
20
lessons/errors/incorrect_wrapping/main.go
Normal file
@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
err1 := errors.New("source error 1")
|
||||
err2 := errors.New("source error 2")
|
||||
err := fmt.Errorf("additional error information: %w and %w", err1, err2)
|
||||
|
||||
fmt.Println(err.Error())
|
||||
fmt.Println(errors.Unwrap(err))
|
||||
|
||||
err = fmt.Errorf("additional error information: %w", "error")
|
||||
|
||||
fmt.Println(err.Error())
|
||||
fmt.Println(errors.Unwrap(err))
|
||||
}
|
||||
29
lessons/errors/many_times_handling_1/main.go
Normal file
29
lessons/errors/many_times_handling_1/main.go
Normal file
@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func GetRoute(lat, lon float32) (string, error) {
|
||||
err := validateCoordinates(lat, lon)
|
||||
if err != nil {
|
||||
fmt.Println("incorrect coordinates") // again
|
||||
return "", err
|
||||
}
|
||||
|
||||
return "route", nil
|
||||
}
|
||||
|
||||
func validateCoordinates(lat, lon float32) error {
|
||||
if lat > 90. || lat < -90. {
|
||||
fmt.Println("incorrect latitude")
|
||||
return errors.New("incorrect latitude")
|
||||
}
|
||||
if lon > 180. || lon < -180. {
|
||||
fmt.Println("incorrect longitude")
|
||||
return errors.New("incorrect longitude")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
26
lessons/errors/many_times_handling_2/main.go
Normal file
26
lessons/errors/many_times_handling_2/main.go
Normal file
@ -0,0 +1,26 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func GetRoute(lat, lon float32) (string, error) {
|
||||
err := validateCoordinates(lat, lon)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("validation error: %w", err)
|
||||
}
|
||||
|
||||
return "route", nil
|
||||
}
|
||||
|
||||
func validateCoordinates(lat, lon float32) error {
|
||||
if lat > 90. || lat < -90. {
|
||||
return errors.New("incorrect latitude")
|
||||
}
|
||||
if lon > 180. || lon < -180. {
|
||||
return errors.New("incorrect longitude")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
34
lessons/errors/multierror/main.go
Normal file
34
lessons/errors/multierror/main.go
Normal file
@ -0,0 +1,34 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/hashicorp/go-multierror"
|
||||
)
|
||||
|
||||
var (
|
||||
ErrNumber1 = errors.New("error 1")
|
||||
ErrNumber2 = errors.New("error 1")
|
||||
ErrNumber3 = errors.New("error 3")
|
||||
)
|
||||
|
||||
// fully compatible with the Go standard library errors package
|
||||
// works for errors.Is, errors.As and errors.Unwrap
|
||||
|
||||
func main() {
|
||||
var err error
|
||||
err = multierror.Append(err, ErrNumber1)
|
||||
err = multierror.Append(err, ErrNumber2)
|
||||
err = fmt.Errorf("internal error: %w", err)
|
||||
|
||||
if errors.Is(err, ErrNumber1) {
|
||||
fmt.Println("found error1 with errors.Is")
|
||||
}
|
||||
if errors.Is(err, ErrNumber2) {
|
||||
fmt.Println("found error2 with errors.Is")
|
||||
}
|
||||
if errors.Is(err, ErrNumber3) {
|
||||
fmt.Println("found error3 with errors.Is")
|
||||
}
|
||||
}
|
||||
15
lessons/errors/nil_pointer_dereference/main.go
Normal file
15
lessons/errors/nil_pointer_dereference/main.go
Normal file
@ -0,0 +1,15 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func dererence(pointer *int) {
|
||||
defer func() {
|
||||
fmt.Println("recovered:", recover())
|
||||
}()
|
||||
|
||||
_ = *pointer
|
||||
}
|
||||
|
||||
func main() {
|
||||
dererence(nil)
|
||||
}
|
||||
29
lessons/errors/oom/main.go
Normal file
29
lessons/errors/oom/main.go
Normal file
@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
// GOGC=off go run main.go
|
||||
|
||||
var data []byte
|
||||
|
||||
func allocate() {
|
||||
defer func() {
|
||||
fmt.Println(recover())
|
||||
}()
|
||||
|
||||
count := 0
|
||||
|
||||
for {
|
||||
data = make([]byte, 1<<30)
|
||||
for idx := 0; idx < 1<<30; idx += 4096 {
|
||||
data[idx] = 100
|
||||
}
|
||||
|
||||
fmt.Println("allocated GB:", count)
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
||||
func main() {
|
||||
allocate()
|
||||
}
|
||||
42
lessons/errors/optional/main.go
Normal file
42
lessons/errors/optional/main.go
Normal file
@ -0,0 +1,42 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
var NullOptional = Optional[int]{}
|
||||
|
||||
type Optional[T any] struct {
|
||||
value T
|
||||
present bool
|
||||
}
|
||||
|
||||
func NewOptional[T any](value T) Optional[T] {
|
||||
return Optional[T]{
|
||||
value: value,
|
||||
present: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (o *Optional[T]) HasValue() bool {
|
||||
return o.present
|
||||
}
|
||||
|
||||
func (o *Optional[T]) Value() T {
|
||||
return o.value
|
||||
}
|
||||
|
||||
func divide(lhs, rhs int) Optional[int] {
|
||||
if rhs == 0 {
|
||||
return NullOptional
|
||||
}
|
||||
|
||||
result := lhs / rhs
|
||||
return NewOptional(result)
|
||||
}
|
||||
|
||||
func main() {
|
||||
x := 100
|
||||
y := 0
|
||||
|
||||
optional := divide(x, y)
|
||||
fmt.Println(optional)
|
||||
}
|
||||
21
lessons/errors/os_exit/main.go
Normal file
21
lessons/errors/os_exit/main.go
Normal file
@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
)
|
||||
|
||||
func process() {
|
||||
defer func() {
|
||||
recover()
|
||||
}()
|
||||
|
||||
fmt.Println("V2: open file")
|
||||
defer fmt.Println("V2: close file")
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func main() {
|
||||
process()
|
||||
}
|
||||
21
lessons/errors/panic/main.go
Normal file
21
lessons/errors/panic/main.go
Normal file
@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func process() {
|
||||
fmt.Println("first")
|
||||
panic("error from process")
|
||||
fmt.Println("second")
|
||||
}
|
||||
|
||||
func main() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println("recover:", r)
|
||||
}
|
||||
}()
|
||||
|
||||
process()
|
||||
}
|
||||
27
lessons/errors/panic_jump/main.go
Normal file
27
lessons/errors/panic_jump/main.go
Normal file
@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
value := func() (result int) {
|
||||
defer func() {
|
||||
v := recover()
|
||||
result = v.(int)
|
||||
}()
|
||||
|
||||
func() {
|
||||
func() {
|
||||
func() {
|
||||
panic(123)
|
||||
// ...
|
||||
}()
|
||||
// ...
|
||||
}()
|
||||
// ...
|
||||
}()
|
||||
|
||||
return
|
||||
}()
|
||||
|
||||
fmt.Println(value)
|
||||
}
|
||||
27
lessons/errors/panic_nil/main.go
Normal file
27
lessons/errors/panic_nil/main.go
Normal file
@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func panicNil() {
|
||||
defer func() {
|
||||
fmt.Println("recovered:", recover())
|
||||
}()
|
||||
|
||||
panic(nil)
|
||||
}
|
||||
|
||||
func panicNilError() {
|
||||
defer func() {
|
||||
fmt.Println("recovered:", recover())
|
||||
}()
|
||||
|
||||
panic(new(runtime.PanicNilError))
|
||||
}
|
||||
|
||||
func main() {
|
||||
panicNil()
|
||||
panicNilError()
|
||||
}
|
||||
27
lessons/errors/panic_rethrow/main.go
Normal file
27
lessons/errors/panic_rethrow/main.go
Normal file
@ -0,0 +1,27 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func process2() {
|
||||
defer func() {
|
||||
e := recover()
|
||||
fmt.Println("#2 recovered:", e)
|
||||
panic(e)
|
||||
}()
|
||||
|
||||
panic("error")
|
||||
}
|
||||
|
||||
func process1() {
|
||||
defer func() {
|
||||
fmt.Println("#1 recovered:", recover())
|
||||
}()
|
||||
|
||||
process2()
|
||||
}
|
||||
|
||||
func main() {
|
||||
process1()
|
||||
}
|
||||
20
lessons/errors/panic_task/main.go
Normal file
20
lessons/errors/panic_task/main.go
Normal file
@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
defer func() {
|
||||
fmt.Println("exited #1")
|
||||
}()
|
||||
|
||||
fmt.Println("started")
|
||||
|
||||
defer func() {
|
||||
recover()
|
||||
fmt.Println("recovered")
|
||||
}()
|
||||
|
||||
panic("exit")
|
||||
|
||||
fmt.Println("exited #2")
|
||||
}
|
||||
29
lessons/errors/panic_with_defer_1/main.go
Normal file
29
lessons/errors/panic_with_defer_1/main.go
Normal file
@ -0,0 +1,29 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func processV1() {
|
||||
defer func() {
|
||||
recover()
|
||||
}()
|
||||
|
||||
fmt.Println("V1: open file")
|
||||
panic("error")
|
||||
fmt.Println("V1: close file")
|
||||
}
|
||||
|
||||
func processV2() {
|
||||
defer func() {
|
||||
recover()
|
||||
}()
|
||||
|
||||
fmt.Println("V2: open file")
|
||||
defer fmt.Println("V2: close file")
|
||||
|
||||
panic("error")
|
||||
}
|
||||
|
||||
func main() {
|
||||
processV1()
|
||||
processV2()
|
||||
}
|
||||
14
lessons/errors/panic_with_defer_2/main.go
Normal file
14
lessons/errors/panic_with_defer_2/main.go
Normal file
@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func process() {
|
||||
fmt.Println("V2: open file")
|
||||
defer fmt.Println("V2: close file")
|
||||
|
||||
panic("error")
|
||||
}
|
||||
|
||||
func main() {
|
||||
process()
|
||||
}
|
||||
21
lessons/errors/recover_without_defer/main.go
Normal file
21
lessons/errors/recover_without_defer/main.go
Normal file
@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func process2() {
|
||||
fmt.Println(recover())
|
||||
panic("error")
|
||||
fmt.Println(recover())
|
||||
}
|
||||
|
||||
func process1() {
|
||||
fmt.Println(recover())
|
||||
process2()
|
||||
fmt.Println(recover())
|
||||
}
|
||||
|
||||
func main() {
|
||||
fmt.Println(recover())
|
||||
process1()
|
||||
fmt.Println(recover())
|
||||
}
|
||||
14
lessons/errors/replace_panic/main.go
Normal file
14
lessons/errors/replace_panic/main.go
Normal file
@ -0,0 +1,14 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
defer func() {
|
||||
fmt.Println("recovered:", recover())
|
||||
}()
|
||||
|
||||
defer panic(3) // replaced panic(3)
|
||||
defer panic(2) // replaced panic(3)
|
||||
defer panic(1) // replaced panic(3)
|
||||
panic(0)
|
||||
}
|
||||
21
lessons/errors/runtime_exit/main.go
Normal file
21
lessons/errors/runtime_exit/main.go
Normal file
@ -0,0 +1,21 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
)
|
||||
|
||||
func process() {
|
||||
defer func() {
|
||||
recover()
|
||||
}()
|
||||
|
||||
fmt.Println("V2: open file")
|
||||
defer fmt.Println("V2: close file")
|
||||
|
||||
runtime.Goexit()
|
||||
}
|
||||
|
||||
func main() {
|
||||
process()
|
||||
}
|
||||
18
lessons/errors/signal_errors/main.go
Normal file
18
lessons/errors/signal_errors/main.go
Normal file
@ -0,0 +1,18 @@
|
||||
package main
|
||||
|
||||
import "database/sql"
|
||||
|
||||
type Database interface {
|
||||
Query(string) (string, error)
|
||||
}
|
||||
|
||||
func RunQueyry(db Database, query string) {
|
||||
_, err := db.Query(query)
|
||||
if err == sql.ErrNoRows {
|
||||
// not found
|
||||
} else if err != nil {
|
||||
// error from database
|
||||
} else {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
20
lessons/errors/stack_overflow/main.go
Normal file
20
lessons/errors/stack_overflow/main.go
Normal file
@ -0,0 +1,20 @@
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func recursion() {
|
||||
var data = [10 * 1024 * 1024]int8{}
|
||||
_ = data
|
||||
|
||||
recursion()
|
||||
}
|
||||
|
||||
func main() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
fmt.Println("Recovered in main:", r)
|
||||
}
|
||||
}()
|
||||
|
||||
recursion()
|
||||
}
|
||||
Reference in New Issue
Block a user