Как я могу подключить Cloud Firestore к Gin framework?

# #firebase #go #google-cloud-firestore #go-gin

#firebase #Вперед #google-cloud-firestore #go-gin

Вопрос:

Как я могу подключить Cloud Firestore к Gin framework? используя main.go и route.go. Я создал проект в cloud firestore с коллекцией «пользователи»

Это мой main.go

 package main

import (
    "context"
    "log"
    "project/routes"

    "github.com/gin-gonic/gin"

    firebase "firebase.google.com/go"

    "google.golang.org/api/option"
)

const (
    projectID      string = "ProjectID"
    collectionName string = "users"
)

func main() {


    // get the db connection and check for error
    app, err := connectDB()
    if err != nil {
        return
    }

    router := gin.Default()

    // all router have access to the db
    router.Use(dbMiddleware(*app))

    usersGroup := router.Group("users")
    {
        usersGroup.POST("register", routes.UsersRegister)
    }

    router.Run()

}

//connecting the api to the firestore
func connectDB() (c *firebase.App, err error) {
    ctx := context.Background()
    opt := option.WithCredentialsFile("path/to/file.json")
    app, err := firebase.NewApp(ctx, nil, opt)
    if err != nil {
        log.Fatalln(err)
        return nil, err
    }

    client, err := app.Firestore(ctx)
    if err != nil {
        log.Fatalln(err)
        return nil, err
    }
    defer client.Close()
    return app, err
}

// create a middleware that attach the db connection to the context
func dbMiddleware(app firebase.App) gin.HandlerFunc {
    return func(c *gin.Context) {
        c.Set("db", app)
        c.Next()
    }
}
  

Это routes / users.go

 package routes

import (
    "fmt"
    "project/models"
    "net/http"

    firebase "firebase.google.com/go"
    "github.com/gin-gonic/gin"
)

func UsersRegister(c *gin.Context) {
    user := models.User{}
    err := c.ShouldBindJSON(amp;user)
    if err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }
    db, _ := c.Get("db")
    app := db.(firebase.App)
    err = user.Register(amp;app)
    if err != nil {
        fmt.Println("Error in user.Register()")
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    c.JSON(http.StatusOK, gin.H{
        "user_id": user.ID,
    })

}

  

Это models / users.go

 package models

import (
    "context"
    "fmt"
    "log"
    "strings"
    "time"

    "cloud.google.com/go/firestore"
    firebase "firebase.google.com/go"

    "github.com/gofrs/uuid"
    "golang.org/x/crypto/bcrypt"
)

const (
    projectID      string = "ProjectId"
    collectionName string = "users"
)

var client *firestore.Client

type User struct {
    ID              uuid.UUID `json:"id"`
    CreatedAt       time.Time `json:"_"`
    UpdatedAt       time.Time `json:"_"`
    FirstName       string    `json:"first_name"`
    LastName        string    `json:"last_name"`
    Email           string    `json:"email"`
    PasswordHash    string    `json:"-"`
    Password        string    `json:"password"`
    PasswordConfirm string    `json:"password_confirm"`
}

func (u *User) Register(app *firebase.App) error {
    if len(u.Password) < 4 || len(u.PasswordConfirm) < 4 {
        return fmt.Errorf("Password must be at least 4 characters long.")
    }

    if u.Password != u.PasswordConfirm {
        return fmt.Errorf("Passwords do not match.")
    }

    if len(u.Email) < 4 {
        return fmt.Errorf("Email must be at least 4 characters long.")
    }

    u.Email = strings.ToLower(u.Email)

    //TO DO check if the email does exist in the db

    // using bcrypt library to hash the password
    pwdHash, err := bcrypt.GenerateFromPassword([]byte(u.Password), bcrypt.DefaultCost)
    if err != nil {
        return fmt.Errorf("There was an error creating your account.")
    }
    u.PasswordHash = string(pwdHash)

    now := time.Now()
    ctx := context.Background()
    defer client.Close()

    if err != nil {
        log.Fatalf(" Failed to create DB")
        return nil
    }
    var user User
    _, _, err = client.Collection(collectionName).Add(ctx, map[string]interface{}{
        "ID":           user.ID,
        "FirstName ":   user.FirstName,
        "LastName":     user.LastName,
        "Email":        user.Email,
        "PasswordHash": user.PasswordHash,
        "CreatedAt":    now,
        "UpdatedAt":    now,
    })
    if err != nil {
        log.Fatalf(" Failed to add new user")
        return nil
    }
    return err

}
  

Сервер запускается, но когда я запускаю postman для отправки http://localhost:8080/users/register/

Я получил это на своем терминале.

 panic recovered:
POST /users/register HTTP/1.1

runtime error: invalid memory address or nil pointer dereference

  

Я пытался подключить к firestore в течение последних 5 дней, но у меня где-то возникла проблема. Заранее спасибо за помощь.

Комментарии:

1. Не могли бы вы попробовать отредактировать свой вопрос, чтобы в нем было немного меньше кода? Было бы неплохо проверить, связана ли проблема с подключением к Firestore или маршрутизацией в Gin. Вы могли бы попробовать просто запустить простой сервер Gin и посмотреть, работает ли он с postman.

2. попробуйте поля структуры пользователя с указателями. Некоторые поля могут быть обнуляемыми.