Golang中错误处理的实现方法与最佳实践
Golang中错误处理的实现方法与最佳实践 我有一个循环,向切片中的网站发送GET请求,这些网站属于结构体类型。
我将分享与遇到的问题相关的最后两个函数。
第一个函数是检查器,接收"[]accountinfo"类型的输入:
func checker(info []accountinfo) {
var request string
var statusCode int
for i := range info {
request = fmt.Sprintf("https://%s/", info[i].domain)
statusCode = getRequest(request)
if statusCode == 200 {
fmt.Println("that's ok")
} else {
fmt.Println(info[i].domain, "not found or content is not valid")
}
}
}
第二个函数发送请求并返回状态码:
func getRequest(url string) int {
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
resp, err := http.Get(url)
if err != nil {
log.Println(err)
}
defer resp.Body.Close()
return resp.StatusCode
}
我遇到了这个错误:
2019/09/05 17:52:18 Get https://something.com/: dial tcp <ip>:443: connect: connection refused
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x40 pc=0x124eebf]
goroutine 1 [running]:
main.getRequest(0xc0000ae0e0, 0x1a, 0x0)
/Users/ozan/monitoring-development/v2/main.go:147 +0xff
main.checker(0xc000584000, 0x8d, 0x100)
/Users/ozan/monitoring-development/v2/main.go:110 +0xd3
main.main()
/Users/ozan/monitoring-development/v2/main.go:67 +0x4dd
exit status 2
Stackoverflow上的人提醒我,由于响应实际上没有完成,所以无法返回状态码,他们的方式让人不太愉快。 我希望这里的人不要像Stackoverflow上的人那样。我真的不明白作为一个新手为什么要被"大师们"攻击。
在这种情况下,我有哪些选择?我想创建一个自定义响应,比如如果连接失败就返回"自定义响应", 然后在第一个函数中,如果返回=="自定义响应"就跳过那个网站。 但我不知道如何实现,或者这是否是一个合适的方法……
如果你能用"愉快的方式"给我一些建议,我会非常高兴。
更多关于Golang中错误处理的实现方法与最佳实践的实战教程也可以访问 https://www.itying.com/category-94-b0.html
检查你的代码,你除了写入日志外没有进行空值处理,而且代码继续执行(defer resp.Body.Close() return resp.StatusCode)
我虽然不是Go语言的"大师",但认为你可以通过返回错误来更符合Go语言的风格。我的意思是:
func getRequest(url string) (int, error) {
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
if resp, err := http.Get(url);
if err != nil {
return -1, err // 使用特定的状态码
}
defer resp.Body.Close()
return resp.StatusCode, nil
}
在检查函数中:
func checker(info []accountinfo) {
var request string
var statusCode int
var err error
for i := range info {
request = fmt.Sprintf("https://%s/", info[i].domain)
statusCode, err = getRequest(request)
if err != nil {
fmt.Println(err)
} else {
if statusCode == 200 {
fmt.Println("正常")
} else {
fmt.Println(info[i].domain, "未找到或内容无效")
}
}
}
}
希望对你有帮助
在Go语言中,错误处理是一个核心特性,你的代码确实存在几个关键问题。主要问题是在getRequest函数中,当http.Get返回错误时,你仍然尝试访问resp.StatusCode,而此时resp可能为nil,导致空指针解引用。
以下是修复后的代码实现:
func checker(info []accountinfo) {
for i := range info {
request := fmt.Sprintf("https://%s/", info[i].domain)
statusCode := getRequest(request)
if statusCode == 200 {
fmt.Println("that's ok")
} else if statusCode == -1 {
fmt.Println(info[i].domain, "connection failed")
} else {
fmt.Println(info[i].domain, "not found or content is not valid, status:", statusCode)
}
}
}
func getRequest(url string) int {
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
resp, err := http.Get(url)
if err != nil {
log.Printf("Request failed for %s: %v", url, err)
return -1 // 自定义错误码表示连接失败
}
defer resp.Body.Close()
return resp.StatusCode
}
更符合Go惯用法的版本是返回错误:
func checker(info []accountinfo) {
for i := range info {
request := fmt.Sprintf("https://%s/", info[i].domain)
statusCode, err := getRequest(request)
if err != nil {
fmt.Printf("%s: %v\n", info[i].domain, err)
continue
}
if statusCode == 200 {
fmt.Println("that's ok")
} else {
fmt.Printf("%s: status code %d\n", info[i].domain, statusCode)
}
}
}
func getRequest(url string) (int, error) {
http.DefaultTransport.(*http.Transport).TLSClientConfig = &tls.Config{InsecureSkipVerify: true}
resp, err := http.Get(url)
if err != nil {
return 0, fmt.Errorf("connection failed: %w", err)
}
defer resp.Body.Close()
return resp.StatusCode, nil
}
对于生产环境,建议添加超时控制:
func getRequest(url string) (int, error) {
client := &http.Client{
Timeout: 10 * time.Second,
Transport: &http.Transport{
TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
},
}
resp, err := client.Get(url)
if err != nil {
return 0, fmt.Errorf("request failed: %w", err)
}
defer resp.Body.Close()
return resp.StatusCode, nil
}
这些修改解决了空指针异常问题,提供了清晰的错误处理路径,并保持了代码的可读性。

