ML
    • Recent
    • Categories
    • Tags
    • Popular
    • Users
    • Groups
    • Register
    • Login

    Extending Packages with Go

    IT Discussion
    golang
    1
    2
    1.6k
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • stacksofplatesS
      stacksofplates
      last edited by stacksofplates

      Go makes extending packages easy. You can easily take a package and add your own functionality. Let's use logging as an example.

      A popular logging package for Go is logrus. It's at "github.com/sirupsen/logrus". So let's start by creating a package of our own and import logrus as a dependency:

      package mangologs
      
      import (
          "github.com/sirupsen/logrus"
      )
      
      

      Now that we've imported logrus, let's extend it by creating our own custom logging entry. Let's say that our company Mangos, Inc requires that we have the app owner and their phone number as part of their application logs (stupid example but you get the point) and that the logs be in JSON format for easier parsing. Let's create our own logging entry so that you don't need to define that every time you write an application:

      package mangologs
      
      import (
          "os"
          "github.com/sirupsen/logrus"
      )
      
      type AppOwner struct {
          Name   string
          Number string
      }
      
      type MangoLogger interface {
          Debug(args ...interface{})
          Info(args ...interface{})
          Print(args ...interface{})
          Warn(args ...interface{})
          Warning(args ...interface{})
          Error(args ...interface{})
          Fatal(args ...interface{})
          Panic(args ...interface{})
      }
      
      var hostName := os.Getenv("HOSTNAME")
      
      func New(name, number string) MangoLogger {
      
          logger := logrus.New()    
      
          logger.SetFormatter(&logrus.JSONFormatter{})
      
          logger.SetReportCaller(true)
      
          entry := logger.WithFields(logrus.Fields{
              "owner_name": name,
              "owner_number": number,
          })
      
          return entry
      
      }
      
      

      We create our own interface that implements only the methods we want our logging package to have. This is both to simplify the example and to show that you can slim down the options available to people if you only want to expose certain things. Then we set the formatting for the logging in the New() function.

      Then in our actual application we call our package:

      package main
      
      import (
          "github.com/mangos/mangologs"
      )
      
      var owner mangologs.AppOwner
      
      func main() {
          owner.Name = "John"
          owner.Number = "555-555-5555"
      
          var log = mangologs.New(owner.Name, owner.Number)
      
          log.Error("something went wrong")
      }
      

      So now our format looks like this

      {"file":"/data/data/com.termux/files/usr/tmp/test.MhzSYLadxB/main.go:15","func":"main.main","level":"error","msg":"something went wrong","owner_name":"John","owner_number":"555-555-5555","time":"2019-10-01T23:58:38Z"}
      

      You can see it includes our file, function name, our level, the owner_name, owner_number, and timestamp.
      Whereas if we just import logrus and did log.Error("something went wrong") it would look like this:

      ERRO[0000] something went wrong
      

      So now any time you want to use this format, you just need to import your package and call the mangologs.New() function with the name and number parameters and it sets up your logging format for you.

      1 Reply Last reply Reply Quote 1
      • stacksofplatesS
        stacksofplates
        last edited by

        In this example you wouldn't have to write an interface, but that's part of the power of Go. Interfaces are defined implicitly.

        1 Reply Last reply Reply Quote 0
        • 1 / 1
        • First post
          Last post