restApi which included CRUD operations
Go is an open-source language
Firstly, we need to install Go
https://golang.org/dl/
I prefer to Visual Studio Code.
https://code.visualstudio.com/
We will create a directory to work in.
https://github.com/faygun/goLangSample
mux, mongo, net/http
go get -u github.com/gorilla/mux
go get go.mongodb.org/mongo-driver
package go.mongodb.org/mongo-driver: no Go files in C:\Users\jjang\go\src\go.mongodb.org\mongo-driver
You must use that driver as go.mongodb.org/mongo-driver/bson
instead.
You should instead refer to the installation instructions here. In short, do this:
go get go.mongodb.org/mongo-driver/mongo
then import it using the same path:
import (
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/bson"
// etc
)
https://stackoverflow.com/questions/55326976/how-to-import-official-mongodb-driver-package/55327043
package main import ( "context" "encoding/json" "log" "net/http" "github.com/gorilla/mux" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" )
https://golang.org/doc/devel/release.html
package models import "go.mongodb.org/mongo-driver/bson/primitive" //Create Struct type Book struct { ID primitive.ObjectID `json:"_id,omitempty" bson:"_id,omitempty"` Isbn string `json:"isbn,omitempty" bson:"isbn,omitempty"` Title string `json:"title" bson:"title,omitempty"` Author *Author `json:"author" bson:"author,omitempty"` } type Author struct { FirstName string `json:"firstname,omitempty" bson:"firstname,omitempty"` LastName string `json:"lastname,omitempty" bson:"lastname,omitempty"` }
package main import ( "context" "encoding/json" "log" "net/http" "github.com/gorilla/mux" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" ) //Connection mongoDB with helper class collection := helper.ConnectDB() func main() { //Init Router r := mux.NewRouter() // arrange our route r.HandleFunc("/api/books", getBooks).Methods("GET") r.HandleFunc("/api/books/{id}", getBook).Methods("GET") r.HandleFunc("/api/books", createBook).Methods("POST") r.HandleFunc("/api/books/{id}", updateBook).Methods("PUT") r.HandleFunc("/api/books/{id}", deleteBook).Methods("DELETE") // set our port address log.Fatal(http.ListenAndServe(":8000", r)) }
package helper import ( "context" "encoding/json" "fmt" "log" "net/http" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) // ConnectDB : This is helper function to connect mongoDB // If you want to export your function. You must to start upper case function name. Otherwise you won't see your function when you import that on other class. func ConnectDB() *mongo.Collection { // Set client options clientOptions := options.Client().ApplyURI("your_cluster_endpoint") // Connect to MongoDB client, err := mongo.Connect(context.TODO(), clientOptions) if err != nil { log.Fatal(err) } fmt.Println("Connected to MongoDB!") collection := client.Database("go_rest_api").Collection("books") return collection } // ErrorResponse : This is error model. type ErrorResponse struct { StatusCode int `json:"status"` ErrorMessage string `json:"message"` } // GetError : This is helper function to prepare error model. // If you want to export your function. You must to start upper case function name. Otherwise you won't see your function when you import that on other class. func GetError(err error, w http.ResponseWriter) { log.Fatal(err.Error()) var response = ErrorResponse{ ErrorMessage: err.Error(), StatusCode: http.StatusInternalServerError, } message, _ := json.Marshal(response) w.WriteHeader(response.StatusCode) w.Write(message) }
func getBooks(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") // we created Book array var books []models.Book // bson.M{}, we passed empty filter. So we want to get all data. cur, err := collection.Find(context.TODO(), bson.M{}) if err != nil { helper.GetError(err, w) return } // Close the cursor once finished /*A defer statement defers the execution of a function until the surrounding function returns. simply, run cur.Close() process but after cur.Next() finished.*/ defer cur.Close(context.TODO()) for cur.Next(context.TODO()) { // create a value into which the single document can be decoded var book models.Book // & character returns the memory address of the following variable. err := cur.Decode(&book) // decode similar to deserialize process. if err != nil { log.Fatal(err) } // add item our array books = append(books, book) } if err := cur.Err(); err != nil { log.Fatal(err) } json.NewEncoder(w).Encode(books) // encode similar to serialize process. }
func getBook(w http.ResponseWriter, r *http.Request) { // set header. w.Header().Set("Content-Type", "application/json") var book models.Book // we get params with mux. var params = mux.Vars(r) // string to primitive.ObjectID id, _ := primitive.ObjectIDFromHex(params["id"]) // We create filter. If it is unnecessary to sort data for you, you can use bson.M{} filter := bson.M{"_id": id} err := collection.FindOne(context.TODO(), filter).Decode(&book) if err != nil { helper.GetError(err, w) return } json.NewEncoder(w).Encode(book) }
func createBook(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var book models.Book // we decode our body request params _ = json.NewDecoder(r.Body).Decode(&book) // insert our book model. result, err := collection.InsertOne(context.TODO(), book) if err != nil { helper.GetError(err, w) return } json.NewEncoder(w).Encode(result) }
func updateBook(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") var params = mux.Vars(r) //Get id from parameters id, _ := primitive.ObjectIDFromHex(params["id"]) var book models.Book // Create filter filter := bson.M{"_id": id} // Read update model from body request _ = json.NewDecoder(r.Body).Decode(&book) // prepare update model. update := bson.D{ {"$set", bson.D{ {"isbn", book.Isbn}, {"title", book.Title}, {"author", bson.D{ {"firstname", book.Author.FirstName}, {"lastname", book.Author.LastName}, }}, }}, } err := collection.FindOneAndUpdate(context.TODO(), filter, update).Decode(&book) if err != nil { helper.GetError(err, w) return } book.ID = id json.NewEncoder(w).Encode(book) }
func deleteBook(w http.ResponseWriter, r *http.Request) { // Set header w.Header().Set("Content-Type", "application/json") // get params var params = mux.Vars(r) // string to primitve.ObjectID id, err := primitive.ObjectIDFromHex(params["id"]) // prepare filter. filter := bson.M{"_id": id} deleteResult, err := collection.DeleteOne(context.TODO(), filter) if err != nil { helper.GetError(err, w) return } json.NewEncoder(w).Encode(deleteResult) }
> go build main.go
and > go run ./