在调用另一个包中的资源时运行时出现恐慌错误。

huangapple go评论71阅读模式
英文:

Runtime panic on calling resource from another package

问题

我正在尝试使用fiber + zap + pgx创建一个简单的API服务器,但是遇到了一个无法解决的错误。

错误信息如下:

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

你的代码如下:

// package main

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"))
}

// package logger

var Say *zap.Logger

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

// package 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") // 这是错误信息中的第19行,位于db包中
    }
    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))

}

错误信息中指示的行数是:

func init() {
    logger.Init()
    env.Init()
    db.Init() // 这是错误信息中的第15行,位于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") // 这是错误信息中的第19行,位于db包中
    }
}

到目前为止,Go的错误信息一直很难解读,我不确定我在这里做错了什么,或者应该如何修复我的代码。

注意:有人建议我使用依赖注入架构。我个人觉得这种模式相当复杂,而且我还在学习Go,所以我希望尽可能保持简单。因此,除非无法修复当前基于全局变量的模式,否则请不要建议我切换模式。

英文:

I am trying to create a simple API server using fiber + zap + pgx
I am getting an error which I am unable to solve.

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

The code so far is;

// package main

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"))
}

// package logger

var Say *zap.Logger

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

// package 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))

}

The lines indicated by the error message

        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

are:

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

and

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
	}

So far go's error messages have been hard to decode and I am not sure what am i doing wrong here or what i should do to fix my code.

Note: I have been told to go for a Dependency Injection arch. I personally find that pattern rather complex, and as I am still learning go, i'd prefer to keep it as simple as I can for now. So would prefer answers to not advise me to switch patterns, unless it is not possible to fix the current global variable based pattern.

答案1

得分: 4

你的各种Init()函数中至少存在两个问题。

  1. 你使用了:=,它在函数作用域内声明了一个新的变量,并不会修改你在作用域外声明的变量。

  2. 你在Init()函数内部使用了defer,这意味着当Init()返回时,延迟执行的函数将被执行。这实际上意味着你的Init函数创建并销毁资源,使其对任何后续代码都无用。

如果你想要给在外部作用域声明的变量赋值,不要使用:=,而是使用=。如果你打算在该函数之外使用conn,则不要在初始化函数内部执行defer conn.Close()等操作。

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("无法连接到数据库", zap.String("详情", err.Error()))
    } else {
        logger.Say.Info("已连接到数据库")
    }
    Conn = c

    var greeting string
    err = Conn.QueryRow(context.Background(), "select 'Hello, this is db!'").Scan(&greeting)
    if err != nil {
        logger.Say.Error("数据库查询失败", zap.String("详情", err.Error()))
    }
    logger.Say.Info("已连接到数据库。数据库返回:", zap.String("详情", 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"))
}
英文:

At least two problems in your various Init() functions.

  1. You're using := which declares a new variable within the scope of the function and does not modify the variable that you declared outside of the scope.

  2. You're using defer inside Init() which is where the defered function will be executed upon when Init() returns. This means, essentially, that your Init creates and then destroys the resource, making it useless for any subsequent code.


If you want to assign to a variable that's declared in an outer scope do NOT use :=, instead use =. And do not do things like defer conn.Close() inside an initializing function if you intend to use conn outside of that function.

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"))
}

huangapple
  • 本文由 发表于 2021年7月10日 15:48:42
  • 转载请务必保留本文链接:https://go.coder-hub.com/68325794.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定