1

It's been few weeks since I joined in Gophers team. So far so good. I started a new project using a fiber web framework to build backend APIs.

I am using MongoDB as my database.

database/db.go

package database

import (
    "context"
    "log"
    "time"

    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
    "go.mongodb.org/mongo-driver/mongo/readpref"
)

var DB *mongo.Database

// InitMongo : Initialize mongodb...
func connectToMongo() {
    log.Printf("Initializing database")

    client, err := mongo.NewClient(options.Client().ApplyURI("mongodb://localhost:27017"))
    if err != nil {
        log.Fatal("Could not able to connect to the database, Reason:", err)
    }
    ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)

    err = client.Connect(ctx)
    if err != nil {
        log.Fatal("Context error, mongoDB:", err)
    }

    //Cancel context to avoid memory leak
    defer cancel()

    defer client.Disconnect(ctx)

    // Ping our db connection
    err = client.Ping(context.Background(), readpref.Primary())
    if err != nil {
        log.Fatal("Ping, mongoDB:", err)
    }

    log.Printf("Database connected!")

    // Create a database
    DB = client.Database("golang-test")

    return
}

// In Golang, init() functions always initialize whenever the package is called.
// So, whenever DB variable called, the init() function initialized
func init() {
    connectToMongo()
}

controllers/mongo.controller/mongo.controller.go

package mongocontroller

import (
    "log"

    "github.com/gofiber/fiber/v2"
    service "gitlab.com/.../services/mongoservice"
)

// GetPersons godoc
// @Summary Get persons.
// @Description Get persons
// @Tags persons
// @Produce json
// @Success 200 {object} []service.Person
// @Failure 400 {object} httputil.HTTPError
// @Failure 404 {object} httputil.HTTPError
// @Failure 500 {object} httputil.HTTPError
// @Router /v1/persons [get]
func GetPersons(c *fiber.Ctx) error {
    res, err := service.GetPersons()
    if err != nil {
        log.Fatal("ERROR: in controller...", err)
    }

    return c.JSON(res)
}

services/mongoservice/mongo.service.go

package mongoservice

import (
    "context"
    "log"

    database "gitlab.com/.../database"
    "go.mongodb.org/mongo-driver/bson"
    "go.mongodb.org/mongo-driver/bson/primitive"
)

// Person : ...
type Person struct {
    ID   primitive.ObjectID `bson:"_id,omitempty" json:"_id,omitempty"`
    Name string             `bson:"name,omitempty" json:"name,omitempty"`
    Age  int                `bson:"age,omitempty" json:"age,omitempty"`
}


func GetPersons() ([]Person, error) {

    ctx := context.Background()

    persons := []Person{}

    log.Printf("mongo data...", ctx)

    cur, err := database.DB.Collection("persons").Find(ctx, bson.M{})
    if err != nil {
        log.Fatal(err)
    }

    // Iterate through the returned cursor.
    for cur.Next(ctx) {
        var person Person
        cur.Decode(&person)
        persons = append(persons, person)
    }

    defer cur.Close(ctx)

    return persons, err
}

Here is my data stored in the database:

enter image description here

The problem is, the line cur, err := database.DB.Collection("persons").Find(ctx, bson.M{}) from service always throwing Client is disconnected.

Any help is appreciated!

Thank you.

The Rock
  • 323
  • 1
  • 8
  • 18
  • you need to move the call to close the database to another function, after your init function gets called the database is initialized but then immediately closed once the function exits because of your call to defer – gold_cy Aug 17 '21 at 12:28
  • Ask the author of fiber. – Volker Aug 17 '21 at 12:48
  • 1
    probably becuz in `database/db.go` you are calling `defer client.Disconnect(ctx)` – Uday Yadav Aug 18 '21 at 07:13

1 Answers1

8

You are calling defer client.Disconnect(ctx) in the same function which is creating the connection (connectToMongo ) so it will close the connection after calling the function. You should return the connection and close after finishing your task. I mean these parts: defer cancel() defer client.Disconnect(ctx)

Omid Tavakoli
  • 156
  • 2
  • 5