Golang中HTTP服务报错:runtime error: invalid memory address or nil pointer dereference

Golang中HTTP服务报错:runtime error: invalid memory address or nil pointer dereference http: 处理请求 [::1]:60288 时发生恐慌:运行时错误:无效的内存地址或空指针解引用 goroutine 21 [运行中]: net/http.(*conn).serve.func1() /usr/local/go/src/net/http/server.go:1801 +0xb9 panic({0x12d5ae0, 0x158de40}) /usr/local/go/src/runtime/panic.go:1047 +0x266 html/template.(*Template).escape(0x0) /usr/local/go/src/html/template/template.go:97 +0x34 html/template.(*Template).Execute(0x0, {0x1388be0, 0xc00017c0e0}, {0x0, 0x0}) /usr/local/go/src/html/template/template.go:121 +0x32 github.com/YRK/jewellery-store/pkg/render.RenderTemplate({0x138f170, 0xc00017c0e0}, {0x131fe4c, 0x0}) /Users/yash_khandelwal943/Desktop/Development/go-code/jewellery-store/pkg/render/render.go:12 +0x9f github.com/YRK/jewellery-store/pkg/handlers.Home({0x138f170, 0xc00017c0e0}, 0x0) /Users/yash_khandelwal943/Desktop/Development/go-code/jewellery-store/pkg/handlers/handlers.go:11 +0x2f net/http.HandlerFunc.ServeHTTP(0x0, {0x138f170, 0xc00017c0e0}, 0x0) /usr/local/go/src/net/http/server.go:2046 +0x2f net/http.(*ServeMux).ServeHTTP(0x0, {0x138f170, 0xc00017c0e0}, 0xc000190200) /usr/local/go/src/net/http/server.go:2424 +0x149 net/http.serverHandler.ServeHTTP({0xc00011d2c0}, {0x138f170, 0xc00017c0e0}, 0xc000190200) /usr/local/go/src/net/http/server.go:2878 +0x43b net/http.(*conn).serve(0xc000138fa0, {0x13903e0, 0xc00011d020}) /usr/local/go/src/net/http/server.go:1929 +0xb08 created by net/http.(*Server).Serve /usr/local/go/src/net/http/server.go:3033 +0x4e8

请帮我解决这个问题!


更多关于Golang中HTTP服务报错:runtime error: invalid memory address or nil pointer dereference的实战教程也可以访问 https://www.itying.com/category-94-b0.html

7 回复

嘿,Yash

你能告诉我你是怎么解决的吗?我正在学习同一门课程。

更多关于Golang中HTTP服务报错:runtime error: invalid memory address or nil pointer dereference的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


感谢Sean,问题出在模板文件上,它无法解析该文件。现在已经解决了。

你好 Jitendra,

请在这种情况下进行错误处理。

parsedTemplate, err := template.ParseFiles("./templates/" + tmpl)
if err != nil {
    log.Fatal("Unable to parse from template:", err)
}

YRK:

parsedTemplate, _ := template.ParseFiles("./templates/" + tmpl)

你在解析文件时忽略了可能发生的任何错误。如果此函数失败,它将返回一个 nil 模板和一个非 nilerror。除非文档说明 error 将为 nil(我目前能想到的唯一例子是 (*strings.Builder).Write* 方法),否则你应该始终检查所有 error 返回值。

你好 Sean,感谢你的回复,

这段代码用于渲染模板:

func RenderTemplate(rw http.ResponseWriter, tmpl string) {
parsedTemplate, _ := template.ParseFiles("./templates/" + tmpl)
err := parsedTemplate.Execute(rw, nil)
if err != nil {
fmt.Println(“error parsing template:”, err)
return
}
}

在我的 main.go 中:

func main() {

http.HandleFunc("/", handlers.Home)
http.HandleFunc("/about", handlers.About)

fmt.Println(fmt.Sprintf(“Starting application on port %s”, portNumber))
err := http.ListenAndServe(portNumber, nil)
if err != nil {
log.Fatal(err)
}
}

没有代码,我们只能猜测问题可能出在哪里。我尝试访问 https://github.com/YRK/jewellery-store/ 查看代码,但收到了 404 错误。可能是私有仓库或者尚未推送代码等原因,所以我无法亲自查看代码。出现“无效内存地址或空指针解引用”这类错误,听起来像是你程序中的某个地方某个东西nil。根据堆栈跟踪,例如:

/usr/local/go/src/html/template/template.go:97 +0x34
html/template.(*Template).Execute(0x0, {0x1388be0, 0xc00017c0e0}, {0x0, 0x0})

Execute( 后面的第一个 0x0 让我相信你的模板是 nil。没有看到你的代码,我无法知道原因。你处理错误了吗?

从错误堆栈来看,这是一个典型的空指针解引用问题。具体发生在 html/template.(*Template).Execute 方法中,因为传入的 *Template 指针为 nil

根据堆栈跟踪,问题出现在 pkg/render/render.go:12RenderTemplate 函数中。以下是可能的原因和解决方案:

问题分析

错误发生在模板执行时,模板对象为 nil。通常是因为:

  1. 模板没有正确初始化
  2. 模板解析失败
  3. 模板缓存为空

解决方案

1. 检查 render.go 文件

// pkg/render/render.go
package render

import (
    "html/template"
    "net/http"
)

var tc = make(map[string]*template.Template)

func RenderTemplate(w http.ResponseWriter, tmpl string) {
    var t *template.Template
    var err error
    
    // 检查模板是否已缓存
    _, inMap := tc[tmpl]
    if !inMap {
        // 模板未缓存,需要解析
        t, err = template.ParseFiles("./templates/" + tmpl)
        if err != nil {
            http.Error(w, err.Error(), http.StatusInternalServerError)
            return
        }
        tc[tmpl] = t
    } else {
        // 从缓存获取模板
        t = tc[tmpl]
    }
    
    // 执行模板前检查是否为 nil
    if t == nil {
        http.Error(w, "模板未找到", http.StatusInternalServerError)
        return
    }
    
    err = t.Execute(w, nil)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

2. 初始化模板缓存

在应用启动时预加载所有模板:

// pkg/render/render.go
package render

import (
    "html/template"
    "io/fs"
    "net/http"
    "path/filepath"
)

var tc map[string]*template.Template

func Init() error {
    tc = make(map[string]*template.Template)
    
    // 加载 templates 目录下的所有 .tmpl 或 .html 文件
    files, err := filepath.Glob("./templates/*.html")
    if err != nil {
        return err
    }
    
    for _, file := range files {
        name := filepath.Base(file)
        t, err := template.ParseFiles(file)
        if err != nil {
            return err
        }
        tc[name] = t
    }
    
    return nil
}

func RenderTemplate(w http.ResponseWriter, tmpl string) {
    t, ok := tc[tmpl]
    if !ok {
        http.Error(w, "模板 "+tmpl+" 未找到", http.StatusInternalServerError)
        return
    }
    
    err := t.Execute(w, nil)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

3. 在主函数中初始化

// main.go
package main

import (
    "log"
    "net/http"
    "github.com/YRK/jewellery-store/pkg/render"
)

func main() {
    // 初始化模板缓存
    err := render.Init()
    if err != nil {
        log.Fatal("无法初始化模板:", err)
    }
    
    // 设置路由
    http.HandleFunc("/", handlers.Home)
    
    log.Println("服务器启动在 :8080")
    err = http.ListenAndServe(":8080", nil)
    if err != nil {
        log.Fatal("服务器启动失败:", err)
    }
}

4. 使用 template.Must 确保模板有效

// pkg/render/render.go
package render

import (
    "html/template"
    "net/http"
    "sync"
)

var (
    tc   map[string]*template.Template
    once sync.Once
)

func loadTemplates() {
    tc = make(map[string]*template.Template)
    
    // 使用 template.Must 确保模板解析成功
    tc["home.page.html"] = template.Must(template.ParseFiles(
        "./templates/base.layout.html",
        "./templates/home.page.html",
    ))
    
    tc["about.page.html"] = template.Must(template.ParseFiles(
        "./templates/base.layout.html",
        "./templates/about.page.html",
    ))
}

func RenderTemplate(w http.ResponseWriter, tmpl string) {
    once.Do(loadTemplates)
    
    t, ok := tc[tmpl]
    if !ok {
        http.Error(w, "模板未找到: "+tmpl, http.StatusInternalServerError)
        return
    }
    
    err := t.Execute(w, nil)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
    }
}

调试建议

handlers.go 中添加调试信息:

// pkg/handlers/handlers.go
package handlers

import (
    "log"
    "net/http"
    "github.com/YRK/jewellery-store/pkg/render"
)

func Home(w http.ResponseWriter, r *http.Request) {
    log.Println("处理 Home 请求,模板: home.page.html")
    render.RenderTemplate(w, "home.page.html")
}

关键是要确保在调用 t.Execute() 之前,模板对象 t 不为 nil。检查模板文件路径是否正确,文件是否存在,以及模板解析是否成功。

回到顶部