package parse import ( "fmt" "runtime" "strings" ) func callerBefore(name string) string { found := false for i := 1; ; i++ { pc, file, line, ok := runtime.Caller(i) if found { return fmt.Sprintf("%s:%d", file, line) } if !ok { return "unknown caller" } f := runtime.FuncForPC(pc) if strings.HasSuffix(f.Name(), "."+name) { found = true } } } type filepos struct { file string line int } func (pos *filepos) String() string { return fmt.Sprintf("%s:%d", pos.file, pos.line) } func callerFilepos(depth int) filepos { // No error handling, because we call this method ourselves with safe depth values. _, file, line, _ := runtime.Caller(depth + 1) return filepos{file, line} } func callerPointer(depth int) uintptr { // No error handling, because we call this method ourselves with safe depth values. p, _, _, _ := runtime.Caller(depth + 1) return p } func callerPanic(name, f string, data ...interface{}) { filepos := callerBefore(name) m := fmt.Sprintf(f, data...) m = strings.Replace(m, "{caller}", filepos, -1) m = strings.Replace(m, "{name}", name, -1) panic(m) }