英文:
How to intercept `runtime.Goexit()` signal
问题
package main
import (
"fmt"
"path"
"runtime"
"strconv"
"time"
"github.com/fatih/color"
"github.com/gin-gonic/gin"
)
var (
Errors map[string]string
err error
)
func CheckErr(err error) {
if err != nil {
pc, file, line, _ := runtime.Caller(1)
color.New(color.FgRed).PrintfFunc()(" [app]")
color.New(color.FgMagenta).PrintfFunc()(fmt.Sprintf("%v:", time.Now().Format("15:04:05.00000")))
color.New(color.FgGreen).PrintfFunc()(fmt.Sprintf("%v] %v:%v:", path.Ext(runtime.FuncForPC(pc).Name())[1:], path.Base(file), line))
color.Yellow(" %v", err)
Errors["app "+time.Now().Format("15:04:05.00000")+" "+path.Ext(runtime.FuncForPC(pc).Name())[1:]+" "+path.Base(file)+":"+strconv.Itoa(line)] = err.Error()
runtime.Goexit()
}
}
func test(hello string) (string, error) {
// ...
if err != nil {
return "", err
}
text := hello + " world"
return text, nil
}
func main() {
router := gin.Default()
router.POST("/hello", func(context *gin.Context) {
message, err := test("hello")
if err != nil {
CheckErr(err)
}
context.JSON(200, gin.H{
"message": message,
"Errors": Errors,
})
})
router.Run(":8080")
}
CheckErr
是一个收集错误日志、打印错误并退出的函数main
是一个 gin 服务test
是 gin 的数据获取函数- 由于
test
需要返回数据,所以不能使用go
协程
> 当 test
失败时,我如何返回到 gin
并返回错误消息?
英文:
package main
import (
"github.com/fatih/color"
"github.com/gin-gonic/gin"
"runtime"
)
var (
Errors map[string]string
err error
)
func CheckErr(err error) {
if err != nil {
pc, file, line, _ := runtime.Caller(1)
color.New(color.FgRed).PrintfFunc()(" [app]")
color.New(color.FgMagenta).PrintfFunc()("%v:", time.Now().Format("15:04:05.00000"))
color.New(color.FgGreen).PrintfFunc()("%v] %v:%v:", path.Ext(runtime.FuncForPC(pc).Name())[1:], path.Base(file), line)
color.Yellow(" %v", err)
Errors["app "+time.Now().Format("15:04:05.00000")+" "+path.Ext(runtime.FuncForPC(pc).Name())[1:]+" "+path.Base(file)+":"+strconv.Itoa(line)] = err.Error()
runtime.Goexit()
}
}
func test(hello string) string{
// ...
if err!=nil{
CheckErr(err)
}
text := hello+" world"
return test
}
func main() {
req.POST("/hello", func(context *gin.Context) {
message:=test("hello")
context.JSON(200, gin.H{
"message": message,
"Errors": Errors,
})
}
}
- CheckErr is a function that collects error logs, prints errors and exits
- main is a gin service
- test is the data acquisition function of gin
- Cannot use
go
coroutine becausetest
needs to return data
> How can I go back to gin
and return the error message when test
fails?
答案1
得分: 2
如果你坚持使用runtime.Goexit()
,那么你必须使用另一个goroutine。结合使用chan
或者sync.WaitGroup
,它可以正常工作,因为Goexit会运行所有的延迟调用。
// Goexit在终止goroutine之前运行所有的延迟调用。因为Goexit不是panic,所以在这些延迟函数中的任何recover调用都将返回nil。
func CheckErr(err error, done chan struct{}) {
defer func() { done <- struct{}{} }()
if err != nil {
// ...
runtime.Goexit()
}
}
func test(hello string) string {
// ...
if err != nil {
done := make(chan struct{})
go CheckErr(err, done)
<-done
}
text := hello + " world"
return text
}
英文:
If you insist on using runtime.Goexit()
then you have to use another goroutine. Together with chan
or sync.WaitGroup
it works just fine since goexit runs all deferred calls.
> // Goexit runs all deferred calls before terminating the goroutine. Because Goexit
// is not a panic, any recover calls in those deferred functions will return nil.
func CheckErr(err error, done chan struct{}) {
defer func() { done <- struct{}{} }()
if err != nil {
// ...
runtime.Goexit()
}
}
func test(hello string) string {
// ...
if err != nil {
done := make(chan struct{})
go CheckErr(err, done)
<-done
}
text := hello + " world"
return text
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论