FAQ
Still feeling my way through the language... Could use a couple of
pointers...

I have the following code in my main program:

func Init() (map[string]string) {
     var err error

     l4g.LoadConfiguration("../resource/l4g.xml")
     l4g.Debug("Init called")
     ....

This code opens a log file for me and starts writing log messages into that
file using a Log4Go library. Works fine.

Now I want to use this logger in code located in other directories in the
project. For example, I have a file named "controllers/user.go". It has
something like this:

package controllers

... more code here...

func NewUserController() *UserController {
     return(&UserController)
}

// GetUser retrieves an individual user resource
func (uc UserController) GetUser(w http.ResponseWriter, r *http.Request, p
httprouter.Params) {
     // Stub an example user
     u := models.User{
         Name: "Bob Smith",
         Gender: "male",
         Age: 50,
         Id: p.ByName("id"),
     }

     // WANT TO LOG A MESSAGE HERE...
....

So how do I pass the l4g object to my controller file. It appears that I
can't add a parameter to the 'GetUser' function directly because that
function is part of an HTTP POST command and it looks like the parameters
are pre-defined - if I'm wrong about that, please let me know.

I think I can pass the l4g object in the constructor function, but I'm not
sure how to store it there so it can be used in other functions that get
called later.

A small example of this would be very useful to me.

Thanks in advance,

nbc

--
You received this message because you are subscribed to the Google Groups "golang-nuts" group.
To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Search Discussions

  • Konstantin Khomoutov at Dec 28, 2015 at 5:27 pm

    On Mon, 28 Dec 2015 08:00:47 -0800 (PST) Neil Cohen wrote:

    I have the following code in my main program:

    func Init() (map[string]string) {
    var err error

    l4g.LoadConfiguration("../resource/l4g.xml")
    l4g.Debug("Init called")
    ....

    This code opens a log file for me and starts writing log messages
    into that file using a Log4Go library. Works fine.

    Now I want to use this logger in code located in other directories in
    the project. For example, I have a file named "controllers/user.go".
    The first thing to carry out before moving forward with Go is to
    completely stop thinking in terms of files. Go is not PHP, and when
    your program starts running, there is no files, and so there's no
    files-related "control flow" in the form of a series of calls to
    `require()` or something like this. When a Go program starts
    executing, the control is passed to a function named "main" in a
    package named "main", and that's all -- nothing is loaded at runtime,
    all the code is already there, compiled.

    So when you think about making some value available *at runtime,* you
    have two choices:

    1) Pass this value to a function you're calling.
    2) Make that value global.

    The method preferred in most cases is surely (1) but for specific tasks
    (2) is the way to go -- when the value is read-only or access to it is
    properly serialized. Good examples for (2) is sql.DB and logging
    provided by the standard library.
    It has something like this:

    package controllers

    ... more code here...

    func NewUserController() *UserController {
    return(&UserController)
    }

    // GetUser retrieves an individual user resource
    func (uc UserController) GetUser(w http.ResponseWriter, r
    *http.Request, p httprouter.Params) {
    // Stub an example user
    u := models.User{
    Name: "Bob Smith",
    Gender: "male",
    Age: 50,
    Id: p.ByName("id"),
    }

    // WANT TO LOG A MESSAGE HERE...
    ....

    So how do I pass the l4g object to my controller file. It appears
    that I can't add a parameter to the 'GetUser' function directly
    because that function is part of an HTTP POST command and it looks
    like the parameters are pre-defined - if I'm wrong about that, please
    let me know.
    Yes, this is correct.

    But there's another approach.

    You're using the most simplistic form of installing handlers for
    a net/http's server, but you can be more explicit: the net/http package
    provides a type, Handler, instances of which can be used to serve
    requests. An example:

       type fooHandler struct {
         l4g log4go.Logger
       }

       func (fh *fooHandler) ServeHTTP(w http.ResponseWriter,
           r *http.Request) {
         fh.l4g.Log("Hey!")
       }

       ...

       handler := fooHandler{
         l4g: myl4gInstance,
       }
       http.Handle("/foo", &handler)

       ...

       http.ListenAndServe(...)

    You appear to use some sort of HTTP routing package; if yes, then look
    for what similar means it provides to provide context for your routing
    functions.

    Now back to what I said earlier about global variables... A logging
    package *might* explicitly state that the instances of "loggers" it
    provides are safe for concurrent uses. While explicitly providing such
    safety in types is an anti-pattern in most cases -- because if you
    don't need it, it will just slow things down, and if you need it you
    might better know how exactly you want this implemented, -- but logging
    is one of such rare instances where built-in serialization is the right
    choice because most of the time logging goes to one or more
    "sinks" (targets), and you'd like to automatically preserve message
    boundaries in each such sink when these messages get sent to it
    concurrently.

    So... I'd check if your log4go package supports serialization on its
    logging objects out of the box, and if yes, just declare and use a
    global variable.

    Now should you go this route, I'll want to make that variable visible
    from several places in your code. That's simple:

    * A global variable declared in a package is visible to all the code in
       the same package.

    * If a global variable is exported, it's visible in all the code which
       imported the package containing that variable.

    IOW, create a package "myapp/log", declare a global and exported
    variable there, import it in all the packages which want to log, use
    that variable in them via "log.MyVar".

    1. https://golang.org/pkg/net/http/#Handler

    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.
  • Neil Cohen at Dec 28, 2015 at 5:53 pm
    Thanks Konstantin - very useful information.

    When I said I had code in other files, I was thinking more of code
    clustering for readability, not so much for control flow - so that isn't an
    issue. But the idea of creating a global logger and making it available to
    everyone is what I think I was looking for. And I will definitely want to
    look closer at handlers - so far I have managed to get a basic http package
    running, but I'm sure there are better ways to do what I'm doing...

    Thanks again,

    nbc

    On Monday, December 28, 2015 at 12:27:55 PM UTC-5, Konstantin Khomoutov
    wrote:
    On Mon, 28 Dec 2015 08:00:47 -0800 (PST)
    Neil Cohen <neilbri...@gmail.com <javascript:>> wrote:
    I have the following code in my main program:

    func Init() (map[string]string) {
    var err error

    l4g.LoadConfiguration("../resource/l4g.xml")
    l4g.Debug("Init called")
    ....

    This code opens a log file for me and starts writing log messages
    into that file using a Log4Go library. Works fine.

    Now I want to use this logger in code located in other directories in
    the project. For example, I have a file named "controllers/user.go".
    The first thing to carry out before moving forward with Go is to
    completely stop thinking in terms of files. Go is not PHP, and when
    your program starts running, there is no files, and so there's no
    files-related "control flow" in the form of a series of calls to
    `require()` or something like this. When a Go program starts
    executing, the control is passed to a function named "main" in a
    package named "main", and that's all -- nothing is loaded at runtime,
    all the code is already there, compiled.

    So when you think about making some value available *at runtime,* you
    have two choices:

    1) Pass this value to a function you're calling.
    2) Make that value global.

    The method preferred in most cases is surely (1) but for specific tasks
    (2) is the way to go -- when the value is read-only or access to it is
    properly serialized. Good examples for (2) is sql.DB and logging
    provided by the standard library.
    It has something like this:

    package controllers

    ... more code here...

    func NewUserController() *UserController {
    return(&UserController)
    }

    // GetUser retrieves an individual user resource
    func (uc UserController) GetUser(w http.ResponseWriter, r
    *http.Request, p httprouter.Params) {
    // Stub an example user
    u := models.User{
    Name: "Bob Smith",
    Gender: "male",
    Age: 50,
    Id: p.ByName("id"),
    }

    // WANT TO LOG A MESSAGE HERE...
    ....

    So how do I pass the l4g object to my controller file. It appears
    that I can't add a parameter to the 'GetUser' function directly
    because that function is part of an HTTP POST command and it looks
    like the parameters are pre-defined - if I'm wrong about that, please
    let me know.
    Yes, this is correct.

    But there's another approach.

    You're using the most simplistic form of installing handlers for
    a net/http's server, but you can be more explicit: the net/http package
    provides a type, Handler, instances of which can be used to serve
    requests. An example:

    type fooHandler struct {
    l4g log4go.Logger
    }

    func (fh *fooHandler) ServeHTTP(w http.ResponseWriter,
    r *http.Request) {
    fh.l4g.Log("Hey!")
    }

    ...

    handler := fooHandler{
    l4g: myl4gInstance,
    }
    http.Handle("/foo", &handler)

    ...

    http.ListenAndServe(...)

    You appear to use some sort of HTTP routing package; if yes, then look
    for what similar means it provides to provide context for your routing
    functions.

    Now back to what I said earlier about global variables... A logging
    package *might* explicitly state that the instances of "loggers" it
    provides are safe for concurrent uses. While explicitly providing such
    safety in types is an anti-pattern in most cases -- because if you
    don't need it, it will just slow things down, and if you need it you
    might better know how exactly you want this implemented, -- but logging
    is one of such rare instances where built-in serialization is the right
    choice because most of the time logging goes to one or more
    "sinks" (targets), and you'd like to automatically preserve message
    boundaries in each such sink when these messages get sent to it
    concurrently.

    So... I'd check if your log4go package supports serialization on its
    logging objects out of the box, and if yes, just declare and use a
    global variable.

    Now should you go this route, I'll want to make that variable visible
    from several places in your code. That's simple:

    * A global variable declared in a package is visible to all the code in
    the same package.

    * If a global variable is exported, it's visible in all the code which
    imported the package containing that variable.

    IOW, create a package "myapp/log", declare a global and exported
    variable there, import it in all the packages which want to log, use
    that variable in them via "log.MyVar".

    1. https://golang.org/pkg/net/http/#Handler
    --
    You received this message because you are subscribed to the Google Groups "golang-nuts" group.
    To unsubscribe from this group and stop receiving emails from it, send an email to golang-nuts+unsubscribe@googlegroups.com.
    For more options, visit https://groups.google.com/d/optout.

Related Discussions

Discussion Navigation
viewthread | post
Discussion Overview
groupgolang-nuts @
categoriesgo
postedDec 28, '15 at 4:00p
activeDec 28, '15 at 5:53p
posts3
users2
websitegolang.org

People

Translate

site design / logo © 2022 Grokbase