出现异常表示着 系统 进入了 一个无法满足用户操作的状态,这个操作可能是显式的, 也可能是隐式的。 这是需要传达一些信息: 1。 发生了什么 : 对异常事件的描述 2。 发生在什么时间, 什么位置 : 异常还应该包含 栈轨信息;异常还应包含对应机器上时间,并最好utc 时间。 3。 对用户友好的信息 : 自定义信息;应该包括前两点的概述; 从用户角度考虑,给出信息 4。 告诉用户如何获得更多信息: 应该提供一个ID; 这个ID对应详细日志。
type MyError struct{
Inner error
Message string
StackTrace string
Misc map[string]interface{}
}
func wrapError(err error, messagef string, msgArgs ...interface{}) MyError{
return MyError{
Inner : err,
Message : fmt.Sprintf(messagef, msgArgs...),
StackTrace: string(debug.Stack()),
Misc : make(map[string]interface{}),
}
}
func (err MyError) Error() string{
return err.Message
}
// lowLevel 模块
type LowLevelErr struct{
error
}
func isGloballyExec(path string)(bool, error){
info ,err := os.Stat(path)
if err !=nil{
return false, LowLevelErr{(wrapError(err, err.Error()))}
}
return info.Mode().Perm() &0100 == 0100, nil
}
// intermediate 模块
type IntermediateErr struct{
error
}
func runJob(id string) error{
const jobBinPath = "/bad/job/binary"
isExecutable, err := isGloballyExec(jobBinPath)
if err != nil{
return err
} else if isExecutable == false{
return wrapError(nil, "job binary is not executable")
}
return exec.Command(jobBinPath, "--id="+id).Run()
}
func handleError(key int, err error, message string){
log.SetPrefix(fmt.Sprintf("[logID:%v]:", key))
log.Printf("%#v", err)
fmt.Printf("[%v] %v", key, message)
}
func main() {
log.SetOutput(os.Stdout)
log.SetFlags(log.Ltime | log.LUTC)
err := runJob("1")
if err != nil{
msg := "There was an unexpected issue; please report this as a bug."
if _, ok := err.(IntermediateErr); ok{
msg = err.Error()
}
handleError(1, err, msg)
}
}
//[logID:1]:10:01:39 main.LowLevelErr{error:main.MyError{Inner:(*os.PathError)(0xc00006e180), Message:"stat /bad/job/binary: no such file or directory", StackTrace:"goroutine 1 [running]:\nruntime/debug.Stack(0xc000016180, 0x2f, 0x0)\n\t/usr/local/go/src/runtime/debug/stack.go:24 +0xa7\nmain.wrapError(0x10ed9e0, 0xc00006e180, 0xc000016180, 0x2f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)\n\t/Users/zhaozhiliang/Documents/work_www/go/src/concurrency/5/exception.go:22 +0xb4\nmain.isGloballyExec(0x10d89cb, 0xf, 0x8, 0x3, 0xc00001e070)\n\t/Users/zhaozhiliang/Documents/work_www/go/src/concurrency/5/exception.go:39 +0xbb\nmain.runJob(0x10d736a, 0x1, 0x22, 0x0)\n\t/Users/zhaozhiliang/Documents/work_www/go/src/concurrency/5/exception.go:51 +0x48\nmain.main()\n\t/Users/zhaozhiliang/Documents/work_www/go/src/concurrency/5/exception.go:71 +0x63\n", Misc:map[string]interface {}{}}}
//[1] There was an unexpected issue; please report this as a bug.
中间模块包装来自lowlevel 模块的异常
func runJob(id string) error{
const jobBinPath = "/bad/job/binary"
isExecutable, err := isGloballyExec(jobBinPath)
if err != nil{
return IntermediateErr{wrapError(err,
"cannot run job %q: requisite binaries not available",
id,
)}
} else if isExecutable == false{
return wrapError(nil,
"cannot run job %q: requisite binaries are not executable",
id,)
}
return exec.Command(jobBinPath, "--id="+id).Run()
}
//[logID:1]:10:13:34 main.IntermediateErr{error:main.MyError{Inner:main.LowLevelErr{error:main.MyError{Inner:(*os.PathError)(0xc00006e180), Message:"stat /bad/job/binary: no such file or directory", StackTrace:"goroutine 1 [running]:\nruntime/debug.Stack(0xc000016180, 0x2f, 0x0)\n\t/usr/local/go/src/runtime/debug/stack.go:24 +0xa7\nmain.wrapError(0x10edc40, 0xc00006e180, 0xc000016180, 0x2f, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, ...)\n\t/Users/zhaozhiliang/Documents/work_www/go/src/concurrency/5/exception.go:22 +0xb4\nmain.isGloballyExec(0x10d8bab, 0xf, 0x1309300, 0x0, 0x203000)\n\t/Users/zhaozhiliang/Documents/work_www/go/src/concurrency/5/exception.go:39 +0xbb\nmain.runJob(0x10d754a, 0x1, 0x22, 0x0)\n\t/Users/zhaozhiliang/Documents/work_www/go/src/concurrency/5/exception.go:87 +0x4b\nmain.main()\n\t/Users/zhaozhiliang/Documents/work_www/go/src/concurrency/5/exception.go:73 +0x63\n", Misc:map[string]interface {}{}}}, Message:"cannot run job \"1\": requisite binaries not available", StackTrace:"goroutine 1 [running]:\nruntime/debug.Stack(0x10ddf7f, 0x33, 0xc000076e80)\n\t/usr/local/go/src/runtime/debug/stack.go:24 +0xa7\nmain.wrapError(0x10edce0, 0xc00000e240, 0x10ddf7f, 0x33, 0xc000076e80, 0x1, 0x1, 0x0, 0x0, 0x0, ...)\n\t/Users/zhaozhiliang/Documents/work_www/go/src/concurrency/5/exception.go:22 +0xb4\nmain.runJob(0x10d754a, 0x1, 0x22, 0x0)\n\t/Users/zhaozhiliang/Documents/work_www/go/src/concurrency/5/exception.go:89 +0x318\nmain.main()\n\t/Users/zhaozhiliang/Documents/work_www/go/src/concurrency/5/exception.go:73 +0x63\n", Misc:map[string]interface {}{}}}
//[1] cannot run job "1": requisite binaries not available