I'm new to Golang, i have been created an api in Golang and MongoDB.
After a hard struggle successfully separate the controller and model packages ,Now i want to define routes in a separate package of routers and access them in main package same like controllers and models.I'm using gorilla/mux package for routing.Anyone can help me please, thanks in Advance!
and here is all of my code:
RESTMONGOMVC/main.go
package main
import (
"RESTMONGOMVC/controllers"
"log"
"net/http"
"github.com/gorilla/mux"
"gopkg.in/mgo.v2"
)
var (
session *mgo.Session
collection *mgo.Collection
err error
)
func getSession() *mgo.Session {
// Connect to our local mongo
s, err := mgo.Dial("mongodb://localhost")
// Check if connection error, is mongo running?
if err != nil {
panic(err)
}
// Deliver session
return s
}
func main() {
var err error
r := mux.NewRouter()
uc := controllers.NewNoteController(getSession())
r.HandleFunc("/api/notes", uc.GetNotes).Methods("GET")
r.HandleFunc("/api/notes", uc.CreateNote).Methods("POST")
r.HandleFunc("/api/notes/{id}", uc.UpdateNote).Methods("PUT")
r.HandleFunc("/api/notes/{id}", uc.DeleteNote).Methods("DELETE")
http.Handle("/api/", r)
http.Handle("/", http.FileServer(http.Dir(".")))
log.Println("Starting Mongodb Session")
session, err = mgo.Dial("localhost")
if err != nil {
panic(err)
}
defer session.Close()
session.SetMode(mgo.Monotonic, true)
collection = session.DB("notesdb").C("notes")
log.Println("Listening on 8080")
http.ListenAndServe(":8080", nil)
}
controllers/note.go
package controllers
import (
"RESTMONGOMVC/models"
"encoding/json"
"log"
"net/http"
"time"
"github.com/gorilla/mux"
"gopkg.in/mgo.v2"
"gopkg.in/mgo.v2/bson"
)
var (
session *mgo.Session
collection *mgo.Collection
err error
)
type (
// UserController represents the controller for operating on the User resource
NoteController struct {
session *mgo.Session
}
)
// NewUserController provides a reference to a UserController with provided mongo session
func NewNoteController(s *mgo.Session) *NoteController {
return &NoteController{s}
}
func (uc NoteController) GetNotes(w http.ResponseWriter, r *http.Request) {
var notes []models.Note
iter := collection.Find(nil).Iter()
result := models.Note{}
for iter.Next(&result) {
notes = append(notes, result)
}
w.Header().Set("Content-Type", "application/json")
j, err := json.Marshal(models.NotesResource{Notes: notes})
if err != nil {
panic(err)
}
w.Write(j)
}
func (uc NoteController) CreateNote(w http.ResponseWriter, r *http.Request) {
var noteResource models.NoteResource
err := json.NewDecoder(r.Body).Decode(¬eResource)
if err != nil {
panic(err)
}
note := noteResource.Note
//get a new Id
obj_id := bson.NewObjectId()
note.Id = obj_id
note.CreatedOn = time.Now()
//Insert into document collection
err = collection.Insert(¬e)
if err != nil {
panic(err)
} else {
log.Printf("Inserted New Record with Title :%s", note.Title)
}
j, err := json.Marshal(models.NoteResource{Note: note})
if err != nil {
panic(err)
}
w.Header().Set("Content-Type", "application/json")
w.Write(j)
}
func (uc NoteController) UpdateNote(w http.ResponseWriter, r *http.Request) {
var err error
//get id from incoming url
vars := mux.Vars(r)
id := bson.ObjectIdHex(vars["id"])
//decode the incoming Note into json
var noteResource models.NoteResource
err = json.NewDecoder(r.Body).Decode(¬eResource)
if err != nil {
panic(err)
}
//partial update on mongodb
err = collection.Update(bson.M{"_id": id},
bson.M{"$set": bson.M{
"title": noteResource.Note.Title,
"decription": noteResource.Note.Description,
}})
if err == nil {
log.Printf("Updated Note : %s", id, noteResource.Note.Title)
} else {
panic(err)
}
w.WriteHeader(http.StatusNoContent)
}
func (uc NoteController) DeleteNote(w http.ResponseWriter, r *http.Request) {
var err error
vars := mux.Vars(r)
id := vars["id"]
//Remove from database
err = collection.Remove(bson.M{"_id": bson.ObjectIdHex(id)})
if err != nil {
log.Printf("Could not find the Note %s to delete", id)
}
w.WriteHeader(http.StatusNoContent)
}
models/note.go
package models
import (
"time"
"gopkg.in/mgo.v2/bson"
)
type Note struct {
Id bson.ObjectId `bson:"_id" json:"id"`
Title string `json:"title"`
Description string `json:"description"`
CreatedOn time.Time `json:"craetedOn"`
}
type NoteResource struct {
Note Note `json:"note"`
}
type NotesResource struct {
Notes []Note `json:"notes"`
}
Not an programming expert but this is how I manage my routes/handlers.
routes/routes.go
package routes
import (
"github.com/gorilla/mux"
)
//NewRouter is main routing entry point
func NewRouter() *mux.Router {
r := mux.NewRouter()
indexHandler(r) // Index handler
fileServer(r) // Fileserver to serve static files
otherLogicalHandler(r) // Other domain/business logic scoped handler
return r
}
routes/indexHandler.go
package routes
import (
"fmt"
"net/http"
"github.com/gorilla/mux"
"github.com/myusername/project/models"
)
func indexHandler(r *mux.Router) {
r.HandleFunc("/", indexMainHandler).Methods("GET")
// Other endpoints goes there if you want to list it in this current indexHandler.go file
// Example: r.HandleFunc("/signup", signupMainHandler).Methods("GET")
}
// Handlers
func indexMainHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=UTF-8")
// Call your model/s there
mydata, err := models.GetMyDataFunction()
if err != nil {
// Handle your error there
return
}
utils.ExecuteTemplate(w, "index.html", struct {
Title string
// Use your model data for templates there
MyData []models.MyData
// Other models/data can go there if multiple data objects used per page.
}{
Title: "Main Page",
MyData: mydata,
})
}
// func signupMainHandler(w http.ResponseWriter, r *http.Request) ...
// Basically repeat the same logic as in indexMainHandler function
routes/fileServer.go
package routes
import (
"net/http"
"github.com/gorilla/mux"
)
func fileServer(r *mux.Router) {
fs := http.FileServer(http.Dir("static"))
r.PathPrefix("/static/").Handler(http.StripPrefix("/static/", fs))
}
routes/otherLogicalHandler.go
... and so on.
As you can see, all they belong to package routes
but are divided into multiple files. File names doesn't actually matter. You can name them as you want.
Models lives in models
directory and also belongs to single package models
package.
Every time you create new routes file, remember to call it in routes.go
file.
Hope this will help for somebody.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With