Golang中如何实现try catch功能
Golang中如何实现try catch功能 我正在使用的包没有提供错误信息,例如:
session := db.driver.New(...)
这会抛出错误:
尝试在已关闭的驱动上创建会话
这是因为我已经有意关闭了驱动。但事实是,现在我想对我的会话错误进行 try...catch:
try {
session := db.driver.New(...)
} catch (err) {
fmt.Println(err)
}
但显然我们没有这样的 try...catch 选项。那么,在这种情况下我们如何进行 try...catch 呢?
如果我记录会话,我得到的是:
&{0x14000020400}
如果我能读取它们,或许就能解决这个问题。但不确定该如何做? 我也尝试了:
fmt.Printf("%v %p\n", &session, session)
但这打印出来像:
0x1400060e030 0x1400060e050
更多关于Golang中如何实现try catch功能的实战教程也可以访问 https://www.itying.com/category-94-b0.html
我做不到。它返回的是指针引用,正如我展示的那样。
更多关于Golang中如何实现try catch功能的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
如果没有错误变量但仍想检查错误,请尝试检查返回变量类型的零值。
try-catch 块用于处理程序执行过程中可能发生的异常或错误,它允许你优雅地处理并从未预期的状况中恢复……
这正是我所寻找的。谢谢。
没看到标记为解决方案的选项。
我无能为力。就是这个函数导致了问题,但返回值中没有错误。它只是返回指针地址。如果我能以某种方式获得可读的值,我会很高兴的。
存在这样的可能性,即该函数仅用于分配一些资源,因此基本上不会发生任何导致错误的情况。在这种情况下,您只需检查使用会话处理程序的其他函数调用所产生的错误。

我认为情况更接近这样。假设,我们发起了一个 POST /api/users 请求,而 main.go 正在运行并服务于该 API。我在这里想要的是,当 /api/user.go 在处理某些事情时出错,例如创建用户时出错,我希望能够重新配置 main.go 并再次调用那个函数来尝试创建用户。希望你现在明白我的意图了。
@skillian 你能再详细指导我一下吗?
我想在 main.go 中处理错误,如果包层级的代码引发了某些错误:
/api/user.go
if someCondition {
// 标记为错误
}
main.go
// 捕获错误
// 执行某些操作
我想我需要使用上下文(context)或协程(goroutine)?我不太确定具体怎么做。
我的观点是,从 panic 中恢复是一个危险信号,表明你正在做错事,而我正试图帮助你找出应对方法。Go 不使用 try ... catch 进行错误处理。要回答你的问题,以下是如何从 panic 中恢复:
session, err := func() (s *Session, err error) {
defer func() {
v := recover()
if v == nil {
return
}
if e, ok := v.(error); ok {
err = e
return
}
err = fmt.Errorf("%v", v)
return
}()
return db.driver.New(...), nil
}()
if err != nil {
// 处理 err
}
// 使用 session 进行一些操作
但要么是:
- 你使用的 API 是一个糟糕的 API,或者
- 你错误地使用了该 API。
我能想到两种实现“包级别”代码的方式:
init函数:
package main
func init() {
if someGlobalVariable != expectedValue {
panic("something is wrong")
}
}
func main() {
// `init` 函数会在 `main` 函数被调用前自动运行。
}
- 通过调用匿名函数来初始化全局变量:
var someGlobalVariable = func() int {
v, err := someFunctionThatCanFail()
if err != nil {
panic("something failed")
}
return v
}()
func main() {
// 如果你能执行到这里,说明 `someGlobalVariable` 已经被设置好了。
}
我只在一种情况下使用过这两种方法:
var currentUser = func() *user.User {
me, err := user.Current()
if err != nil {
panic(fmt.Errorf("failed to get current user: %w", err))
}
return me
}()
func main() {
defaultConfigPath := filepath.Join(currentUser.HomeDir, ".config", "myApp")
}
如果你正在寻找重试逻辑,你可以直接检查错误并重试最多 n 次。这里有一个使用闭包的示例:
在特定于 HTTP 请求的情况下,你可以使用自定义处理程序来重试一次:
package main
import (
"log"
"net/http"
)
func main() {
mux := http.NewServeMux()
mux.Handle("/user", RetryHandler(CreateUser))
log.Fatal(http.ListenAndServe(":8090", mux))
}
// Will call f() and retry once if it returns an error
func RetryHandler(f func(w http.ResponseWriter, r *http.Request) error) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
err := f(w, r)
// We had a problem. Retry the request
if err != nil {
err = f(w, r)
}
// TODO: add global error handling logic here?
})
}
func CreateUser(w http.ResponseWriter, r *http.Request) error {
// Create user and return errors
return nil
}
这里的注意事项当然是,在确定没有错误之前,你需要在 CreateUser 中不要写入 w。你不希望开始写入 w,然后返回一个错误,这会导致 RetryHandler 再次调用 CreateUser 处理程序。
可能也有用的东西:
- 你也可以添加
retryCount int作为RetryHandler的参数。 - 你也可以重构
RetryHandler使其通用,并处理对象的反序列化/序列化,这样它只需调用一个函数,然后将该函数返回的任何内容发送到w。自从泛型出现并使这变得容易以来,我以前就做过这个。 - 你可以添加一个退避延迟,而不是立即重试。
- 你可以添加全局错误处理,正如我在代码中提到的。
最后,有一些旨在帮助处理重试的包,例如:
你可以试试那个。

