英文:
http: panic serving [::1]:58965: runtime error: invalid memory address or nil pointer dereference
问题
Go初学者,尝试创建一个简单的应用程序来读取CSV文件。然而,我认为我对错误的处理不够好,导致当我访问路径时应用程序失败。
我的代码:
package handlers
import (
"fmt"
"net/http"
"os"
"github.com/gocarina/gocsv"
)
type Client struct {
origin string `csv:"origin"`
destination string `csv:"destination"`
flight_num string `csv:"flight_num"`
origin_latitude float32 `csv:"origin_latitude"`
origin_longitude float32 `csv:"origin_longitude"`
destination_latitude float32 `csv:"destination_latitude"`
destination_longitude float32 `csv:"destination_longitude"`
}
func (s *Server) getWeather(w http.ResponseWriter, r *http.Request) {
in, err := os.Open("data.csv")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
defer in.Close()
clients := []*Client{}
if err = gocsv.UnmarshalFile(in, &clients); err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
for _, client := range clients {
fmt.Println("Hello, ", client.origin)
}
}
错误日志:
2022/07/10 12:57:57 == route: /weather
2022/07/10 12:57:57 == method: GET
2022/07/10 12:57:57 http: panic serving [::1]:51696: runtime error: invalid memory address or nil pointer dereference
goroutine 34 [running]:
net/http.(*conn).serve.func1()
C:/Program Files/Go/src/net/http/server.go:1801 +0xb9
panic({0x1023780, 0x12b6b40})
C:/Program Files/Go/src/runtime/panic.go:1047 +0x266
health-check/api/handlers.(*Server).getWeather(0xd6d3e7, {0x10d4230, 0xc0001a21c0}, 0xc000162000)
C:/Users/anjar/challenge/training-A830284/health-check/api/handlers/weather.go:93 +0x135
health-check/api/middlewares.MiddlewaresJSON.func1({0x10d4230, 0xc0001a21c0}, 0xc0000a0200)
C:/Users/anjar/challenge/training-A830284/health-check/api/middlewares/middlewares.go:18 +0x191
net/http.HandlerFunc.ServeHTTP(0xc0000a0100, {0x10d4230, 0xc0001a21c0}, 0x16bfa961548)
C:/Program Files/Go/src/net/http/server.go:2046 +0x2f
github.com/gorilla/mux.(*Router).ServeHTTP(0xc000148000, {0x10d4230, 0xc0001a21c0}, 0xc00018c500)
C:/Users/anjar/go/pkg/mod/github.com/gorilla/mux@v1.8.0/mux.go:210 +0x1cf
net/http.serverHandler.ServeHTTP({0xc0001824e0}, {0x10d4230, 0xc0001a21c0}, 0xc00018c500)
C:/Program Files/Go/src/net/http/server.go:2878 +0x43b
net/http.(*conn).serve(0xc00049e000, {0x10d55a0, 0xc00010f110})
C:/Program Files/Go/src/net/http/server.go:1929 +0xb08
created by net/http.(*Server).Serve
C:/Program Files/Go/src/net/http/server.go:3033 +0x4e8
根据我在网上阅读的内容,似乎是错误处理不好导致的问题?想知道如何修复这个问题以及我做错了什么。
英文:
Go beginner, trying to create a simple app that reads a CSV file. However I think my poor handling of errors is causing my app to fail when I hit the path.
My code:
package handlers
import (
"fmt"
"net/http"
"os"
"github.com/gocarina/gocsv"
)
type Client struct {
origin string `csv:"origin"`
destination string `csv:"destination"`
flight_num string `csv:"flight_num"`
origin_latitude float32 `csv:"origin_latitude"`
origin_longitude float32 `csv:"origin_longitude"`
destination_latitude float32 `csv:"destination_latitude"`
destination_longitude float32 `csv:"destination_longitude"`
}
func (s *Server) getWeather(w http.ResponseWriter, r *http.Request) {
in, err := os.Open("data.csv")
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
defer in.Close()
clients := []*Client{}
if err = gocsv.UnmarshalFile(in, &clients); err != nil {
w.WriteHeader(http.StatusInternalServerError)
}
for _, client := range clients {
fmt.Println("Hello, ", client.origin)
}
}
Error log:
2022/07/10 12:57:57 == route: /weather
2022/07/10 12:57:57 == method: GET
2022/07/10 12:57:57 http: panic serving [::1]:51696: runtime error: invalid memory address or nil pointer dereference
goroutine 34 [running]:
net/http.(*conn).serve.func1()
C:/Program Files/Go/src/net/http/server.go:1801 +0xb9
panic({0x1023780, 0x12b6b40})
C:/Program Files/Go/src/runtime/panic.go:1047 +0x266
health-check/api/handlers.(*Server).getWeather(0xd6d3e7, {0x10d4230, 0xc0001a21c0}, 0xc000162000)
C:/Users/anjar/challenge/training-A830284/health-check/api/handlers/weather.go:93 +0x135
health-check/api/middlewares.MiddlewaresJSON.func1({0x10d4230, 0xc0001a21c0}, 0xc0000a0200)
C:/Users/anjar/challenge/training-A830284/health-check/api/middlewares/middlewares.go:18 +0x191
net/http.HandlerFunc.ServeHTTP(0xc0000a0100, {0x10d4230, 0xc0001a21c0}, 0x16bfa961548)
C:/Program Files/Go/src/net/http/server.go:2046 +0x2f
github.com/gorilla/mux.(*Router).ServeHTTP(0xc000148000, {0x10d4230, 0xc0001a21c0}, 0xc00018c500)
C:/Users/anjar/go/pkg/mod/github.com/gorilla/mux@v1.8.0/mux.go:210 +0x1cf
net/http.serverHandler.ServeHTTP({0xc0001824e0}, {0x10d4230, 0xc0001a21c0}, 0xc00018c500)
C:/Program Files/Go/src/net/http/server.go:2878 +0x43b
net/http.(*conn).serve(0xc00049e000, {0x10d55a0, 0xc00010f110})
C:/Program Files/Go/src/net/http/server.go:1929 +0xb08
created by net/http.(*Server).Serve
C:/Program Files/Go/src/net/http/server.go:3033 +0x4e8
From what I read online it seems to be a poor handling of errors? Would like to know how I can fix this and what I'm doing wrong.
答案1
得分: 1
你的代码中有更多的错误:
如果 err == nil
,你会返回 HTTP 500,但没有返回语句,所以代码会继续执行。如果发生任何错误,应该立即返回。
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
在你的结构体中,你必须以大写字母开头命名字段。在 Go 中,通过将字段的首字母大写来导出(公开)字段。
type Client struct {
Origin string `csv:"origin"`
Destination string `csv:"destination"`
...
}
英文:
There are more bugs in your code:
If the err == nil
you give HTTP 500, but do not return, so the code runs. Return if any error occurs.
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
In your struct, you have to start your fields with a Capital letter. In go
you can export (make public) fields by capitalize the first letter of its name.
type Client struct {
Origin string `csv:"origin"`
Destination string `csv:"destination"`
...
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论