Go Lang HTTP连接未找到

huangapple go评论75阅读模式
英文:

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.

huangapple
  • 本文由 发表于 2014年9月5日 08:49:51
  • 转载请务必保留本文链接:https://go.coder-hub.com/25677101.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定