Code Monkey home page Code Monkey logo

Comments (11)

chmac avatar chmac commented on June 1, 2024

I tried to implement something along the lines of mikebthun/negronicql but I couldn't get it to work. Here's what I tried:

package renderer

import (
    "github.com/gorilla/context"
    "gopkg.in/unrolled/render.v1"
    "net/http"
)

type RenderMiddleware struct {
    Render *render.Render
}

func New(render *render.Render) *RenderMiddleware {
    return &RenderMiddleware{render}
}

func (render RenderMiddleware) ServeHTTP(rw http.ResponseWriter, r *http.Request, next http.HandlerFunc) {

    // Attach the renderer
    context.Set(r, "Render", render.Render)

    // Call the next middleware handler
    next(rw, r)

}

Then in my package main I have:

    render := render.New(render.Options{})
    renderer := renderer.New(render)
    n.Use(renderer)

Then I can successfully use render := context.Get(r, "Render") later, but when I try to use render.JSON() I get this:

render.JSON undefined (type interface {} has no field or method JSON)

It's getting pretty late here, so I'm probably missing something obvious, in which case, if I work it out tomorrow morning, I'll post the answer here and close the ticket. :-)

from render.

chmac avatar chmac commented on June 1, 2024

Arg, found it. I knew it was something simple and stupid. Instead of render := context.Get(r, "Render") I need to use render := context.Get(req, "Render").(*render.Render). I knew it was simple. :-)

from render.

unrolled avatar unrolled commented on June 1, 2024

Glad you got it figured out!

from render.

runemadsen avatar runemadsen commented on June 1, 2024

Is this an advised solution? I've been trying to figure out the same thing, but it seems weird to attach an existing renderer on every single call to a middleware handler?

from render.

unrolled avatar unrolled commented on June 1, 2024

While the solution above works, I personally have taken a different approach in most of my apps. Just like you would normally create a global DB variable somewhere and always refer to that, I create a Render variable somewhere convenient and use that:

// Render is the global renderer for all views.
var Render *render.Render

// Then you can initialize it or add this to a setup method elsewhere.
func init() {
    Render = render.New(render.Options{
        // options live here
    })
}

from render.

runemadsen avatar runemadsen commented on June 1, 2024

Awesome, thanks a bunch!

from render.

chmac avatar chmac commented on June 1, 2024

@unrolled Thanks for sharing your example, really helpful. Are there any multi threading considerations here? Is Render threadsafe? In your example, it would be possible for two simultaneous executions of Render.JSON(), are there any variables which might cause issues there?

I'm super new to Go, so you probably know the idioms better than me. Is creating a single DB variable the idiomatic approach? I saw the negronicql package attaching the DB handler to the session, but that may be the exception rather than the norm. I'd be grateful for any opinion you want to share.

from render.

chmac avatar chmac commented on June 1, 2024

My very inexperienced and pretty crude reading of the render.go and engine.go code didn't find any potential thread conflicts, but I don't understand the paradigm nearly well enough to be anything like confident in my conclusion.

I'd guess if it's not possible to set any options after the Render instance has been created, then it's probably thread safe by default, but I'll wait for your reply @unrolled before jumping to any conclusions. :-)

from render.

unrolled avatar unrolled commented on June 1, 2024

A global render.Render object is threadsafe. Once it is initialized, the package is basically static. So no worries regarding race conditions or simultaneous executions.

For the DB variable, I would yes it's idiomatic to create a single instance and refer to that from everywhere. Be sure to refer to the global variable rather than passing the pointer along though, passing the pointer could led to issues if something changes the global variable.

A good example of this can be found here: https://github.com/sourcegraph/thesrc/blob/master/datastore/db.go

from render.

arycloud avatar arycloud commented on June 1, 2024

Can anyone help me Plz!
I want to make a separate package for routers and put all of my routes into this package and access them in my main package, according to url request, i'm using mux for routing and net/http.
Here is my main.go from Main Package

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

from render.

elithrar avatar elithrar commented on June 1, 2024

You can just export the *http.ServeMux represented by your r variable.

i.e.

package handler

// You could also pass in an *Env struct that embeds your mgo connection and other
// "application wide" services that your routes need to use.
func Routes(session *mgo.Session) *http.ServeMux {
    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)
    // Truncated for brevity

    return r
}

... and in your main package:

package main

func main() {
    r := handler.Routes(getSession())

    // Pass your `http.ServeMux` to ListenAndServe
    http.ListenAndServe(":8080", r)
}

Basic example but I hope that's clear. Further questions might be better off asked on https://groups.google.com/forum/?fromgroups#!forum/golang-nuts or http://stackoverflow.com/questions/tagged/go

from render.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.