英文:
Go Lang HTTP Connection Not Found
问题
我是一个Go的新手,正在编写一个脚本来测试我的Web服务器是否正常运行,如果不正常则发送邮件通知。除了一个令人头疼的问题外,一切都正常,我已经尝试了其他一些解决方案。
问题是当Web服务器完全关闭并且没有响应时,Go会崩溃:
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x1 addr=0x0 pc=0x40140e]
goroutine 16 [running]:
runtime.panic(0x68b1c0, 0x83bfe2)
c:/go/src/pkg/runtime/panic.c:279 +0x11f
main.httpGET(0x6f0530, 0x15)
httpcheck.go
:57 +0x32e
main.main()
httpcheck.go
:43 +0x3b
goroutine 19 [finalizer wait]:
runtime.park(0x415bb0, 0x840c38, 0x83eda9)
c:/go/src/pkg/runtime/proc.c:1369 +0xac
runtime.parkunlock(0x840c38, 0x83eda9)
c:/go/src/pkg/runtime/proc.c:1385 +0x42
runfinq()
c:/go/src/pkg/runtime/mgc0.c:2644 +0xdd
runtime.goexit()
c:/go/src/pkg/runtime/proc.c:1445
exit status 2
以下是直到崩溃的部分代码:
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"github.com/sendgrid/sendgrid-go"
"os"
"time"
"net"
)
var finishedWaiting bool
var timeout = time.Duration(2) * time.Second
var httpClient = http.DefaultClient
func main() {
const url = "http://doesnotexist.com"
httpGET(url)
log.Println("main is running")
}
func httpGET(url string) {
log.Println("httpGet is runnning")
resp, err := httpClient.Get(url)
if err != nil && !doesFileExist("down") {
}
if resp.StatusCode != 200 && !doesFileExist("down") {
isDown()
} else if resp.StatusCode == 200 && doesFileExist("down") {
log.Println("200 response")
sendmail("up")
removeDownFile()
}
}
func sendmail(status string) {
sg := sendgrid.NewSendGridClient("user", "pass")
message := sendgrid.NewMail()
message.AddTo("admin@website.com")
message.AddToName("WebBot")
if status == "down" {
message.SetSubject("Websites Down")
message.SetText("Sites may be down")
} else {
message.SetSubject("Website Up")
message.SetText("Sites are back Up")
}
message.SetFrom("admin@website.com")
if r := sg.Send(message); r == nil {
fmt.Println("Email sent!")
} else {
fmt.Println(r)
}
}
//checks if the file name is present
func doesFileExist(name string) bool {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}
// write down file
func writeDownFile() {
contents, _ := ioutil.ReadFile("")
ioutil.WriteFile("down", contents, 0x777)
}
//remove down file if server is back up
func removeDownFile() {
os.Remove("down")
}
func sleepForTen() {
log.Println("sleeping for 10.....")
time.Sleep(10000 * time.Millisecond)
finishedWaiting = true
main()
}
func isDown() {
if finishedWaiting != true {
sleepForTen()
} else {
writeDownFile()
log.Println("200 response")
sendmail("down")
}
}
希望能给我一个指引,帮助我优雅地确定是否无法建立连接。
谢谢。
英文:
I'm a newbie to Go, writing a script to test whether my web-server's are up and mai if not. Everything's working except one niggling issue which is driving me crazy, tried quite a few solutions posted elsewhere.
The issue is when the web server is totally down and does not reply, Go is crashing:
panic: runtime error: invalid memory address or nil pointer dereference
[signal 0xc0000005 code=0x1 addr=0x0 pc=0x40140e]
goroutine 16 [running]:
runtime.panic(0x68b1c0, 0x83bfe2)
c:/go/src/pkg/runtime/panic.c:279 +0x11f
main.httpGET(0x6f0530, 0x15)
httpcheck.go
:57 +0x32e
main.main()
httpcheck.go
:43 +0x3b
goroutine 19 [finalizer wait]:
runtime.park(0x415bb0, 0x840c38, 0x83eda9)
c:/go/src/pkg/runtime/proc.c:1369 +0xac
runtime.parkunlock(0x840c38, 0x83eda9)
c:/go/src/pkg/runtime/proc.c:1385 +0x42
runfinq()
c:/go/src/pkg/runtime/mgc0.c:2644 +0xdd
runtime.goexit()
c:/go/src/pkg/runtime/proc.c:1445
exit status 2
Here's what i have till the crash....
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"github.com/sendgrid/sendgrid-go"
"os"
"time"
"net"
)
var finishedWaiting bool
var timeout = time.Duration(2) * time.Second
var httpClient = http.DefaultClient
func main() {
const url = "http://doesnotexist.com"
httpGET(url)
log.Println("main is running")
}
func httpGET(url string) {
log.Println("httpGet is runnning")
resp, err := httpClient.Get(url)
if err != nil && !doesFileExist("down") {
}
if resp.StatusCode != 200 && !doesFileExist("down") {
isDown()
} else if resp.StatusCode == 200 && doesFileExist("down") {
log.Println("200 response")
sendmail("up")
removeDownFile()
}
}
func sendmail(status string) {
sg := sendgrid.NewSendGridClient("user", "pass")
message := sendgrid.NewMail()
message.AddTo("admin@website.com")
message.AddToName("WebBot")
if status == "down" {
message.SetSubject("Websites Down")
message.SetText("Sites may be down")
} else {
message.SetSubject("Website Up")
message.SetText("Sites are back Up")
}
message.SetFrom("admin@website.com")
if r := sg.Send(message); r == nil {
fmt.Println("Email sent!")
} else {
fmt.Println(r)
}
}
//checks if the file name is present
func doesFileExist(name string) bool {
if _, err := os.Stat(name); err != nil {
if os.IsNotExist(err) {
return false
}
}
return true
}
// write down file
func writeDownFile() {
contents, _ := ioutil.ReadFile("")
ioutil.WriteFile("down", contents, 0x777)
}
//remove down file if server is back up
func removeDownFile() {
os.Remove("down")
}
func sleepForTen() {
log.Println("sleeping for 10.....")
time.Sleep(10000 * time.Millisecond)
finishedWaiting = true
main()
}
func isDown() {
if finishedWaiting != true {
sleepForTen()
} else {
writeDownFile()
log.Println("200 response")
sendmail("down")
}
}
A nudge in the right direction would be appreciated, to help me gracefully determine if the connection cant be established at all.
Thanks.
答案1
得分: 2
问题在于你忽略了err
对象。resp
可能是空值,因为出现了错误,当你尝试访问resp.StatusCode
时会导致恐慌。我不确定doesFileExist
的目的是什么,但可以尝试以下代码:
func httpGET(url string) {
log.Println("httpGet is runnning")
resp, err := httpClient.Get(url)
if err != nil || resp.StatusCode != 200 && !doesFileExist("down") {
isDown()
} else if resp.StatusCode == 200 && doesFileExist("down") {
log.Println("200 response")
sendmail("up")
removeDownFile()
}
}
英文:
The problem is that you're ignoring the err
object. resp
is probably nil because of this error, which causes a panic when you try to access resp.StatusCode
. I'm not sure what's the point with doesFileExist
, but try this :
func httpGET(url string) {
log.Println("httpGet is runnning")
resp, err := httpClient.Get(url)
if err != nil || resp.StatusCode != 200 && !doesFileExist("down") {
isDown()
} else if resp.StatusCode == 200 && doesFileExist("down") {
log.Println("200 response")
sendmail("up")
removeDownFile()
}
}
答案2
得分: 0
你正在尝试检查resp.StatusCode
,即使Get方法返回了一个错误。在这种情况下,http.Response
是无效的,可能为nil,或者包含nil指针,因此你不能使用它。
英文:
You're trying to check resp.StatusCode
even if the Get returned an error. The http.Response
is not valid in this case, and may be nil, or contain nil pointers, so you cannot use it.
答案3
得分: -1
如果在get
中发生错误,你只需继续执行程序。难怪后面resp
会是空值。
当然,这只是一个猜测,因为我们只能猜测行号。
英文:
If an error occurs in the get
you just continue with the program. No wonder resp
will be nil later.
That's ofc only a guess, since we can only guess the line numbers.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论