代码之家  ›  专栏  ›  技术社区  ›  Rishav Sharan

Golang运行时从另一个包调用资源时出现死机

  •  1
  • Rishav Sharan  · 技术社区  · 3 年前

    我遇到了一个我无法解决的错误。

    PS C:\Users\risharan\Documents\GitHub\freya> go run .\src\freya.go
    panic: runtime error: invalid memory address or nil pointer dereference
    [signal 0xc0000005 code=0x0 addr=0x0 pc=0xcdca67]
    
    goroutine 1 [running]:
    go.uber.org/zap.(*Logger).check(0x0, 0xc000060500, 0xff0b96, 0x15, 0x0)
            C:/Users/risharan/go/pkg/mod/go.uber.org/zap@v1.18.1/logger.go:268 +0x987
    go.uber.org/zap.(*Logger).Info(0x0, 0xff0b96, 0x15, 0x0, 0x0, 0x0)
            C:/Users/risharan/go/pkg/mod/go.uber.org/zap@v1.18.1/logger.go:191 +0x4b
    freya/src/db.Init()
            C:/Users/risharan/Documents/GitHub/freya/src/db/db.go:19 +0x6db
    main.init.0()
            C:/Users/risharan/Documents/GitHub/freya/src/freya.go:15 +0x31
    exit status 2
    

    目前为止的准则是:;

    func init() {
        logger.Init()
        env.Init()
        db.Init()
    }
    
    func main() {
    
        app := fiber.New()
    
        app.Get("/", func(c *fiber.Ctx) error {
            return c.SendString("Hello, World!")
        })
    
        log.Fatal(app.Listen(":3000"))
    }
    

    //程序包记录器

    var Say *zap.Logger
    
    func Init() {
        Say, _ := zap.NewProduction()
        defer Say.Sync()
    }
    

    //包db

    var Conn *pgxpool.Pool
    
    func Init() {
        c, err := pgxpool.Connect(context.Background(), env.Conf["DATABASE_URL"])
        if err != nil {
            logger.Say.Fatal("Can't connect to DB", zap.String("Details", err.Error()))
        } else {
            logger.Say.Info("Connected to Database")
        }
        Conn = c
    
        defer Conn.Close()
    
        var greeting string
        err = Conn.QueryRow(context.Background(), "select 'Hello, this is db!'").Scan(&greeting)
        if err != nil {
            logger.Say.Error("DB Query failed", zap.String("Details", err.Error()))
        }
        logger.Say.Info("Connected to DB. DB says; ", zap.String("Details", greeting))
    
    }
    

            C:/Users/risharan/Documents/GitHub/freya/src/db/db.go:19 +0x6db
    main.init.0()
            C:/Users/risharan/Documents/GitHub/freya/src/freya.go:15 +0x31
    

    是:

    func init() {
        logger.Init()
        env.Init()
        db.Init() // this is the line 15 as shown in error message in package main
    }
    

    func Init() {
        c, err := pgxpool.Connect(context.Background(), env.Conf["DATABASE_URL"])
        if err != nil {
            logger.Say.Fatal("Can't connect to DB", zap.String("Details", err.Error()))
        } else {
            logger.Say.Info("Connected to Database") // this is the line 19 in the error message in the package db
        }
    

    注意:我被告知要进行依赖注入。我个人觉得这个模式相当复杂,因为我还在学习围棋,所以我现在还是尽量保持简单。所以我宁愿回答不建议我切换模式,除非不可能修复当前基于全局变量的模式。

    1 回复  |  直到 3 年前
        1
  •  1
  •   mkopriva    3 年前

    Init() 功能。

    1. 你用的是 := 宣布 在函数作用域内的变量,并且不修改在作用域外声明的变量。

    2. defer 里面 初始化() 这就是延迟函数将在何时执行的地方 初始化() 返回。这意味着,基本上,你的 Init 创建然后销毁资源,使其对任何后续代码都无用。


    := = . 不要做这样的事 defer conn.Close() 如果要使用 conn 在这个功能之外。

    var Say *zap.Logger
    
    func Init() {
        Say, _ = zap.NewProduction()
    }
    
    var Conn *pgxpool.Pool
    
    func Init() {
        c, err := pgxpool.Connect(context.Background(), env.Conf["DATABASE_URL"])
        if err != nil {
            logger.Say.Fatal("Can't connect to DB", zap.String("Details", err.Error()))
        } else {
            logger.Say.Info("Connected to Database")
        }
        Conn = c
    
        var greeting string
        err = Conn.QueryRow(context.Background(), "select 'Hello, this is db!'").Scan(&greeting)
        if err != nil {
            logger.Say.Error("DB Query failed", zap.String("Details", err.Error()))
        }
        logger.Say.Info("Connected to DB. DB says; ", zap.String("Details", greeting))
    }
    
    func init() {
        logger.Init()
        env.Init()
        db.Init()
    }
    
    func main() {
        defer func() {
            db.Conn.Close()
            logger.Say.Sync()
        }()
    
        app := fiber.New()
    
        app.Get("/", func(c *fiber.Ctx) error {
            return c.SendString("Hello, World!")
        })
    
        log.Fatal(app.Listen(":3000"))
    }