英文:
Gorm Panic golang : panic serving runtime error: invalid memory address or nil pointer dereference
问题
我正在尝试解决这个恐慌错误,我刚刚在GOLANG中创建了一个后端,那段代码是我的第一步,如果你看到了一些错误,请告诉我!
这是代码的第一部分,主要是Main函数(main.go),位于main包中:
如果你看到,我们有两个函数:
- main()
- BindRoutes(function()) -> 当从main函数调用时,它接收一个绑定器
func main() {
err := godotenv.Load(".env")
if err != nil {
log.Fatal(err)
}
// 数据库变量用于结构体
host := os.Getenv("POSTGRES_HOST")
user := os.Getenv("POSTGRES_USER")
port := os.Getenv("POSTGRES_PORT")
password := os.Getenv("POSTGRES_PASSWORD")
dbname := os.Getenv("POSTGRES_DB")
// 服务器变量
PORT := os.Getenv("PORT")
JWT_SECRET := os.Getenv("JWT_SECRET")
DB_URL := os.Getenv("DATA_BASE_URL")
server, err := server.NewServer(context.Background(), &server.Config{
JWTSecret: JWT_SECRET,
Port: PORT,
DatabaseUrl: DB_URL,
})
if err != nil {
log.Fatal(err)
}
db := config.Database{
Host: host,
Port: port,
User: user,
Password: password,
Dbname: dbname,
}
db.Open()
server.Start(BindRoutes)
}
func BindRoutes(s server.Server, r *mux.Router, db *config.Database) {
r.HandleFunc("/blog/newblog", handler.CreateNewBlog(s, db)).Methods(http.MethodPost)
}
接下来是SERVER包:
这里有两个结构体和一个接口,最重要的部分是绑定器,我不知道我是否实现得好。
package server
import (
"context"
"errors"
"log"
"net/http"
"github.com/felipeolayao1998/backdiariodeuninge/config"
"github.com/gorilla/mux"
)
type Config struct {
Port string
JWTSecret string
DatabaseUrl string
}
type Server interface {
Config() *Config
}
type Broker struct {
config *Config
router *mux.Router
}
func (b *Broker) Config() *Config {
return b.config
}
func NewServer(ctx context.Context, config *Config) (*Broker, error) {
if config.Port == "" {
return nil, errors.New("port is required")
}
if config.JWTSecret == "" {
return nil, errors.New("jwt secret is required")
}
if config.DatabaseUrl == "" {
return nil, errors.New("database url is required")
}
broker := &Broker{
config: config,
router: mux.NewRouter(),
}
return broker, nil
}
func (b *Broker) Start(binder func(s Server, r *mux.Router, db *config.Database)) {
b.router = mux.NewRouter()
binder(b, b.router, &config.Database{})
log.Println("starting server on port", b.config.Port)
if err := http.ListenAndServe(b.config.Port, b.router); err != nil {
log.Println("error starting server:", err)
} else {
log.Fatalf("server stopped")
}
}
Models:
package Models
type Blog struct {
Id string `json:"id" gorm:"type:string;default:string;primary_key;unique"`
Name string `json:"name" gorm:"type:varchar(255);not null"`
Content string `json:"content" gorm:"type:varchar(2000);not null"`
Likes int `json:"likes" gorm:"type:integer"`
}
Handler:
这里有个问题,当我调用create函数时,它返回一个恐慌错误,你可以在问题的最后看到。
func CreateNewBlog(s server.Server, db *config.Database) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-type", "application/json")
w.WriteHeader(http.StatusOK)
db.Db.Create(&models.Blog{Id: "1", Name: "Felipe", Content: "fdasfasfa", Likes: 1}) // 这里是问题所在
}
}
2023/04/07 21:25:46 starting server on port :8000
0xc00043a028 &{a2081199-a75e-4b3e-9551-3442a0fe0d21 Felipe contenido ejempo 1}
2023/04/07 21:25:55 http: panic serving [::1]:59553: runtime error: invalid memory address or nil pointer dereference
goroutine 18 [running]:
net/http.(*conn).serve.func1()
C:/Program Files/Go/src/net/http/server.go:1850 +0xbf
panic({0x1620000, 0x1c52680})
C:/Program Files/Go/src/runtime/panic.go:890 +0x262
gorm.io/gorm.(*DB).Create(0x17e44c0?, {0x15d11c0?, 0xc00041c180?})
C:/Users/Bymet/go/pkg/mod/gorm.io/gorm@v1.24.7-0.20230306060331-85eaf9eeda11/finisher_api.go:18 +0x22
github.com/felipeolayao1998/backdiariodeuninge/handler.CreateNewBlog.func1({0x17ea340, 0xc000424000}, 0xc00042c100)
D:/PodCast/PaginaWeb/backend/handler/handlerBlog.go:69 +0x3e5
英文:
I'm trying to solve this panic error, i'm just created a backend in GOLANG, that code was my first steps, also if u see some mistakes, tell me!.
Here was the firts part of code , the Main: (main.go) into the package main:
if you see we have 2 functions
-
main()
-
BindRoutes(function()) -> it recieves a binder when it's called from the main
func main() { err := godotenv.Load(".env") if err != nil { log.Fatal(err) } // Variables de la base de datos para el struct host := os.Getenv("POSTGRES_HOST") user := os.Getenv("POSTGRES_USER") port := os.Getenv("POSTGRES_PORT") password := os.Getenv("POSTGRES_PASSWORD") dbname := os.Getenv("POSTGRES_DB") // Variables del servidor PORT := os.Getenv("PORT") JWT_SECRET := os.Getenv("JWT_SECRET") DB_URL := os.Getenv("DATA_BASE_URL") server, err := server.NewServer(context.Background(), &server.Config{ JWTSecret: JWT_SECRET, Port: PORT, DatabaseUrl: DB_URL, }) if err != nil { log.Fatal(err) } db := config.Database{ Host: host, Port: port, User: user, Password: password, Dbname: dbname, } db.Open() server.Start(BindRoutes) } func BindRoutes(s server.Server, r *mux.Router, db *config.Database) { r.HandleFunc("/blog/newblog", handler.CreateNewBlog(s, db)).Methods(http.MethodPost) }
Next we have the SERVER package
Here we have 2 structs and 1 interface, there the most important part is the binder, there I don't know if i implemented good.
```
package server
import (
"context"
"errors"
"log"
"net/http"
"github.com/felipeolayao1998/backdiariodeuninge/config"
"github.com/gorilla/mux"
)
type Config struct {
Port string
JWTSecret string
DatabaseUrl string
}
type Server interface {
Config() *Config
}
type Broker struct {
config *Config
router *mux.Router
}
func (b *Broker) Config() *Config {
return b.config
}
func NewServer(ctx context.Context, config *Config) (*Broker, error) {
if config.Port == "" {
return nil, errors.New("port is required")
}
if config.JWTSecret == "" {
return nil, errors.New("jwt secret is required")
}
if config.DatabaseUrl == "" {
return nil, errors.New("database url is required")
}
broker := &Broker{
config: config,
router: mux.NewRouter(),
}
return broker, nil
}
func (b *Broker) Start(binder func(s Server, r *mux.Router, db *config.Database)) {
b.router = mux.NewRouter()
binder(b, b.router, &config.Database{})
log.Println("starting server on port", b.config.Port)
if err := http.ListenAndServe(b.config.Port, b.router); err != nil {
log.Println("error starting server:", err)
} else {
log.Fatalf("server stopped")
}
}
```
Models:
```
package Models
type Blog struct {
Id string `json:"id" gorm:"type:string;default:string;primary_key;unique"`
Name string `json:"name" gorm:"type:varchar(255);not null"`
Content string `json:"content" gorm:"type:varchar(2000);not null"`
Likes int `json:"likes" gorm:"type:integer" `
}
```
Handler:
Here i have the problem, when i call the create, it returns an PANIC as you can see at the end of this question.
func CreateNewBlog(s server.Server, db *config.Database) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-type", "application/json")
w.WriteHeader(http.StatusOK)
db.Db.Create(&models.Blog{Id: "1", Name: "Felipe", Content: "fdasfasfa", Likes: 1}) //Here is the problem
}
}
2023/04/07 21:25:46 starting server on port :8000
0xc00043a028 &{a2081199-a75e-4b3e-9551-3442a0fe0d21 Felipe contenido ejempo 1}
2023/04/07 21:25:55 http: panic serving [::1]:59553: runtime error: invalid memory address or nil pointer dereference
goroutine 18 [running]:
net/http.(*conn).serve.func1()
C:/Program Files/Go/src/net/http/server.go:1850 +0xbf
panic({0x1620000, 0x1c52680})
C:/Program Files/Go/src/runtime/panic.go:890 +0x262
gorm.io/gorm.(*DB).Create(0x17e44c0?, {0x15d11c0?, 0xc00041c180?})
C:/Users/Bymet/go/pkg/mod/gorm.io/gorm@v1.24.7-0.20230306060331-85eaf9eeda11/finisher_api.go:18 +0x22
github.com/felipeolayao1998/backdiariodeuninge/handler.CreateNewBlog.func1({0x17ea340, 0xc000424000}, 0xc00042c100)
D:/PodCast/PaginaWeb/backend/handler/handlerBlog.go:69 +0x3e5
</details>
# 答案1
**得分**: 2
你正在将一个未初始化的指针传递给`db`变量的`Db`字段的`Create`方法。
你可以尝试先初始化db连接。
```go
func CreateNewBlog(s server.Server, db *config.Database) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-type", "application/json")
w.WriteHeader(http.StatusOK)
// 初始化数据库连接
err := db.Open()
if err != nil {
log.Fatal(err)
}
// 在数据库中创建一个新的博客记录
db.Db.Create(&models.Blog{Id: "1", Name: "Felipe", Content: "fdasfasfa", Likes: 1})
}
}
英文:
You are passing an uninitialized pointer to the Create
method of the Db
field of the db
variable.
Can you try to initialize the db connection first?
func CreateNewBlog(s server.Server, db *config.Database) http.HandlerFunc {
return func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-type", "application/json")
w.WriteHeader(http.StatusOK)
// Initialize the database connection
err := db.Open()
if err != nil {
log.Fatal(err)
}
// Create a new blog record in the database
db.Db.Create(&models.Blog{Id: "1", Name: "Felipe", Content: "fdasfasfa", Likes: 1})
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论