去 http 恐慌服务

Go http panic serving

我感到恐慌:

C:\Users\loow\Desktop\USBWebserver v8.5\duplicate_submissions>go run server.go
2015/10/23 13:00:39 http: panic serving [::1]:63867: runtime error: invalid memo
ry address or nil pointer dereference
goroutine 5 [running]:
net/http.(*conn).serve.func1(0xc0820a1810, 0x3b55b8, 0xc082024040)
        c:/go/src/net/http/server.go:1287 +0xbc
main.login(0x2990058, 0xc0820d4000, 0xc0820be1c0)
        C:/Users/loow/Desktop/USBWebserver v8.5/duplicate_submissions/server.go:
27 +0x5a5
net/http.HandlerFunc.ServeHTTP(0x8326a8, 0x2990058, 0xc0820d4000, 0xc0820be1c0)
        c:/go/src/net/http/server.go:1422 +0x41
net/http.(*ServeMux).ServeHTTP(0xc082062360, 0x2990058, 0xc0820d4000, 0xc0820be1
c0)
        c:/go/src/net/http/server.go:1699 +0x184
net/http.serverHandler.ServeHTTP(0xc08200c360, 0x2990058, 0xc0820d4000, 0xc0820b
e1c0)
        c:/go/src/net/http/server.go:1862 +0x1a5
net/http.(*conn).serve(0xc0820a1810)
        c:/go/src/net/http/server.go:1361 +0xbf5
created by net/http.(*Server).Serve
        c:/go/src/net/http/server.go:1910 +0x3fd
2015/10/23 13:00:39 http: panic serving [::1]:63868: runtime error: invalid memo
ry address or nil pointer dereference
goroutine 33 [running]:
net/http.(*conn).serve.func1(0xc082114000, 0x3b55b8, 0xc082112000)
        c:/go/src/net/http/server.go:1287 +0xbc
main.login(0x2990058, 0xc0821140b0, 0xc0821200e0)
        C:/Users/loow/Desktop/USBWebserver v8.5/duplicate_submissions/server.go:
27 +0x5a5
net/http.HandlerFunc.ServeHTTP(0x8326a8, 0x2990058, 0xc0821140b0, 0xc0821200e0)
        c:/go/src/net/http/server.go:1422 +0x41
net/http.(*ServeMux).ServeHTTP(0xc082062360, 0x2990058, 0xc0821140b0, 0xc0821200
e0)
        c:/go/src/net/http/server.go:1699 +0x184
net/http.serverHandler.ServeHTTP(0xc08200c360, 0x2990058, 0xc0821140b0, 0xc08212
00e0)
        c:/go/src/net/http/server.go:1862 +0x1a5
net/http.(*conn).serve(0xc082114000)
        c:/go/src/net/http/server.go:1361 +0xbf5
created by net/http.(*Server).Serve
        c:/go/src/net/http/server.go:1910 +0x3fd
exit status 2

编写此代码:

package main

import(
    "fmt"
    "net/http"
    "html/template"
    "log"
    "time"
    "crypto/md5"
    "io"
    "strconv"
)

func loginForm(w http.ResponseWriter, r *http.Request){

}

func login(w http.ResponseWriter, r *http.Request){
    fmt.Println(r.Method)
    if r.Method == "GET"{
        cruTime := time.Now().Unix()
        h := md5.New()
        io.WriteString(h,strconv.FormatInt(cruTime,10))
        token := fmt.Sprintf("%x", h.Sum(nil))
        fmt.Println(token)
        t, err := template.ParseFiles("templates/index.gtpl")
        fmt.Println(err.Error())
        err = t.Execute(w, token)
        fmt.Println(err.Error())
    } else{
        r.ParseForm()
        token := r.Form.Get("token")
        if token != ""{
            fmt.Println(token)
        } else{
            fmt.Println("There is no token")
        }
        fmt.Println("username length: ", len(r.Form["username"][0]))
        fmt.Println("username: ", template.HTMLEscapeString(r.Form.Get("username")))
        fmt.Println("password: ", template.HTMLEscapeString(r.Form.Get("password")))
        template.HTMLEscape(w, []byte(r.Form.Get("username")))

    }
}

func main(){
    http.HandleFunc("/", loginForm)
    http.HandleFunc("/login", login)
    err := http.ListenAndServe(":9090", nil)
    if err != nil {
        log.Fatal("ListenAndServe: ", err)
    }
}

我无法修复它,我尝试了我在 Whosebug 中找到的所有内容。问题是什么?没有报错,panic说问题在t,err := template.ParseFiles("templates/index.gtpl")..

有模板文件:

<input type="checkbox" name="interest" value="football">Football
<input type="checkbox" name="interest" value="basketball">Basketball
<input type="checkbox" name="interest" value="tennis">Tennis
Username: <input type="text" name="username">
Password: <input type="password" name="password">
<input type="hidden" name="token" value="{{.}}">
<input type="submit" value="Login">

恐慌堆栈跟踪为您提供以下信息:

2015/10/23 13:00:39 http: panic serving [::1]:63868: runtime error: invalid memory address or nil pointer dereference goroutine 33 [running]:

这意味着您正在尝试访问不存在的内容(nil 指针)。

那么来自您的文件的第一行就是这一行:

v8.5/duplicate_submissions/server.go:27

那里有:

26: t, err := template.ParseFiles("templates/index.gtpl")
27: fmt.Println(err.Error())
28: err = t.Execute(w, token)

表示err为nil

解决方案

如果出现错误,则无法继续该过程。这就是为什么你不能只打印出错误的原因。为了优雅地停止进程,您需要 return 一个 HTTP 状态代码,然后 return。对于上述情况,您可以 return 代码 500(内部服务器错误)。

t, err := template.ParseFiles("templates/index.gtpl")
if err != nil {
  fmt.Println(err) // Ugly debug output
  w.WriteHeader(http.StatusInternalServerError) // Proper HTTP response
  return
}

对于 template.ParseFilest.Execute 也必须这样做。

顺便说一句,这叫做 "comma ok" 模式