github.com/hikaru7719/go@v0.0.0-20181025140707-c8b2ac68906a/src/runtime/error.go (about) 1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package runtime 6 7 import "internal/bytealg" 8 9 // The Error interface identifies a run time error. 10 type Error interface { 11 error 12 13 // RuntimeError is a no-op function but 14 // serves to distinguish types that are run time 15 // errors from ordinary errors: a type is a 16 // run time error if it has a RuntimeError method. 17 RuntimeError() 18 } 19 20 // A TypeAssertionError explains a failed type assertion. 21 type TypeAssertionError struct { 22 _interface *_type 23 concrete *_type 24 asserted *_type 25 missingMethod string // one method needed by Interface, missing from Concrete 26 } 27 28 func (*TypeAssertionError) RuntimeError() {} 29 30 func (e *TypeAssertionError) Error() string { 31 inter := "interface" 32 if e._interface != nil { 33 inter = e._interface.string() 34 } 35 as := e.asserted.string() 36 if e.concrete == nil { 37 return "interface conversion: " + inter + " is nil, not " + as 38 } 39 cs := e.concrete.string() 40 if e.missingMethod == "" { 41 msg := "interface conversion: " + inter + " is " + cs + ", not " + as 42 if cs == as { 43 // provide slightly clearer error message 44 if e.concrete.pkgpath() != e.asserted.pkgpath() { 45 msg += " (types from different packages)" 46 } else { 47 msg += " (types from different scopes)" 48 } 49 } 50 return msg 51 } 52 return "interface conversion: " + cs + " is not " + as + 53 ": missing method " + e.missingMethod 54 } 55 56 // An errorString represents a runtime error described by a single string. 57 type errorString string 58 59 func (e errorString) RuntimeError() {} 60 61 func (e errorString) Error() string { 62 return "runtime error: " + string(e) 63 } 64 65 // plainError represents a runtime error described a string without 66 // the prefix "runtime error: " after invoking errorString.Error(). 67 // See Issue #14965. 68 type plainError string 69 70 func (e plainError) RuntimeError() {} 71 72 func (e plainError) Error() string { 73 return string(e) 74 } 75 76 type stringer interface { 77 String() string 78 } 79 80 func typestring(x interface{}) string { 81 e := efaceOf(&x) 82 return e._type.string() 83 } 84 85 // printany prints an argument passed to panic. 86 // If panic is called with a value that has a String or Error method, 87 // it has already been converted into a string by preprintpanics. 88 func printany(i interface{}) { 89 switch v := i.(type) { 90 case nil: 91 print("nil") 92 case bool: 93 print(v) 94 case int: 95 print(v) 96 case int8: 97 print(v) 98 case int16: 99 print(v) 100 case int32: 101 print(v) 102 case int64: 103 print(v) 104 case uint: 105 print(v) 106 case uint8: 107 print(v) 108 case uint16: 109 print(v) 110 case uint32: 111 print(v) 112 case uint64: 113 print(v) 114 case uintptr: 115 print(v) 116 case float32: 117 print(v) 118 case float64: 119 print(v) 120 case complex64: 121 print(v) 122 case complex128: 123 print(v) 124 case string: 125 print(v) 126 default: 127 print("(", typestring(i), ") ", i) 128 } 129 } 130 131 // panicwrap generates a panic for a call to a wrapped value method 132 // with a nil pointer receiver. 133 // 134 // It is called from the generated wrapper code. 135 func panicwrap() { 136 pc := getcallerpc() 137 name := funcname(findfunc(pc)) 138 // name is something like "main.(*T).F". 139 // We want to extract pkg ("main"), typ ("T"), and meth ("F"). 140 // Do it by finding the parens. 141 i := bytealg.IndexByteString(name, '(') 142 if i < 0 { 143 throw("panicwrap: no ( in " + name) 144 } 145 pkg := name[:i-1] 146 if i+2 >= len(name) || name[i-1:i+2] != ".(*" { 147 throw("panicwrap: unexpected string after package name: " + name) 148 } 149 name = name[i+2:] 150 i = bytealg.IndexByteString(name, ')') 151 if i < 0 { 152 throw("panicwrap: no ) in " + name) 153 } 154 if i+2 >= len(name) || name[i:i+2] != ")." { 155 throw("panicwrap: unexpected string after type name: " + name) 156 } 157 typ := name[:i] 158 meth := name[i+2:] 159 panic(plainError("value method " + pkg + "." + typ + "." + meth + " called using nil *" + typ + " pointer")) 160 }