go.charczuk.com@v0.0.0-20240327042549-bc490516bd1a/sdk/errutil/new.go (about) 1 /* 2 3 Copyright (c) 2023 - Present. Will Charczuk. All rights reserved. 4 Use of this source code is governed by a MIT license that can be found in the LICENSE file at the root of the repository. 5 6 */ 7 8 package errutil 9 10 import ( 11 "encoding/json" 12 "errors" 13 "fmt" 14 ) 15 16 var ( 17 _ error = (*Exception)(nil) 18 _ fmt.Formatter = (*Exception)(nil) 19 _ json.Marshaler = (*Exception)(nil) 20 ) 21 22 // New returns a new error with a call stack. 23 // 24 // Pragma: this violates the rule that you should take interfaces and return 25 // concrete types intentionally; it is important for the semantics of typed pointers and nil 26 // for this to return an interface because (*Ex)(nil) != nil, but (error)(nil) == nil. 27 func New(class interface{}, options ...Option) error { 28 return NewDepth(class, DefaultErrorStartDepth, options...) 29 } 30 31 // NewDepth creates a new exception with a given start point of the stack. 32 func NewDepth(class interface{}, startDepth int, options ...Option) error { 33 if class == nil { 34 return nil 35 } 36 37 var ex *Exception 38 switch typed := class.(type) { 39 case *Exception: 40 if typed == nil { 41 return nil 42 } 43 ex = typed 44 case error: 45 if typed == nil { 46 return nil 47 } 48 49 ex = &Exception{ 50 Class: typed, 51 Inner: errors.Unwrap(typed), 52 StackTrace: Callers(startDepth), 53 } 54 case string: 55 ex = &Exception{ 56 Class: Class(typed), 57 StackTrace: Callers(startDepth), 58 } 59 default: 60 ex = &Exception{ 61 Class: Class(fmt.Sprint(class)), 62 StackTrace: Callers(startDepth), 63 } 64 } 65 for _, option := range options { 66 option(ex) 67 } 68 return ex 69 }