Golang(14)Error Handle Debugging Logging

Golang(14)Error Handle Debugging Logging

1. Error Handle
func Open(name string) (file *File, err error)

It will return the err if we open file fail.

f, err := os.Open(“filename.ext”)
if err != nil {
     log.Fatal(err)
}

Error Type
type error interface {
     Error() string
}

There is one method in the interface error.
implementation of error interface

type errorString struct {
     s string
}

func (e *errorString) Error() string {
     return e.s
}

fund New(text string) error {
     return &errorString{text}
}

We can use New to create one error instance.

For example>
func Sqrt(f float64) (float64, error) {
     if f < 0 {
          return 0, errors.New(“math: square root of negative number”)
     }
     …snip...
}

Customer Error Type

type SyntaxError struct {
     msg        string
     Offset     int64
}

func (e *SyntaxError) Error() string { return e.msg }

Error Handle
We can deal the error in our router like this>
func viewRecord(w http.ResponseWriter, r *http.Request) {
     …snip…
     if err := datastore.Get(c, key, record); err != nil {
          http.Error(w, err.Error(), 500)
          return
     }
     if err := viewTemplate.Execute(w, record); err != nil {
          http.Error(w, err.Error(), 500)
     }
}

It works, but we need to put these error handle codes there again and again.

type appHandler func(http.ResponseWriter, *http.Request) error

func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
     if err := fn(w,r); err != nil {
          http.Error(w, err.Error(), 500)
     }
}

func init() {
     http.Handle(“/view”, appHandler(viewRecord))
}

Then our viewRecord function can be like this.
func viewRecord(w http.ResponseWriter, r *http.Request) error {
     …snip..
     if err := datastore.Get(c, key, record); err != nil {
          return err
     }
     return viewTemplate.Execute(w, record)
}

We can define the Error Type ourselves.

type appError struct {
     Error           error
     Message    string
     Code           int
}

type appHandler func(http.ResponseWriter, *http.Request) *appError

func (fn appHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
     if e := fn(w, r); e != nil {
          http.Error(w, e.Message, e.Code)
     }
}

If we use our customized Error Type, we can change the viewRecord like this.
func viewRecord(w http.ResponseWriter, r *http.Request) *appError {
     …snip…
     if err := datastore.Get(c, key, record); err != nil {
          return &appError{err, “record not found”, 404 }
     }
     if err := viewTemplate.Execute(w, record); err != nil {
          return &appError{err, “Can not display record”, 500}
     }
     return nil
}

2. Use GDB Debugging
…snip...

3. Writing the Test
…snip…

4. Try seelog

Install the module
>go get -u github.com/cihub/seelog

The Simplest Example works
package main

import log "github.com/cihub/seelog"

func main() {
     defer log.Flush()
     log.Info("Hello from Seelog!")
}

Create the module logs
I create the directory and file logs/LogCustom.go with codes
package logs

import (
     "fmt"
     seelog "github.com/cihub/seelog"
)

var Logger seelog.LoggerInterface

func loadAppConfig() {
     logger, err := seelog.LoggerFromConfigAsFile("/Users/carl/work/easy/easygo/src/com/sillycat/easygoapp/seelog.xml")
     if err != nil {
          fmt.Println(err)
          return
     }
     UseLogger(logger)
}

func init() {
     DisableLog()
     loadAppConfig()
}

// DisableLog disables all library log output
func DisableLog() {
     Logger = seelog.Disabled
}

// UseLogger uses a specified seelog.LoggerInterface to output library log.
// Use this func if you are using Seelog logging system in your app.
func UseLogger(newLogger seelog.LoggerInterface) {
     Logger = newLogger
}

My logsee.xml will be as follow, we can change more configure based the doc from seelog
<seelog type="adaptive" mininterval="2000000" maxinterval="100000000" critmsgcount="500" minlevel="debug">
    <exceptions>
        <exception filepattern="test*" minlevel="error"/>
    </exceptions>
    <outputs formatid="all">
        <file path="all.log"/>
        <filter levels="info">
          <console formatid="fmtinfo"/>
        </filter>
        <filter levels="error,critical" formatid="fmterror">
          <console/>
          <file path="errors.log"/>
        </filter>
    </outputs>
    <formats>
        <format id="fmtinfo" format="[%Level] [%Time] %Msg%n"/>
        <format id="fmterror" format="[%LEVEL] [%Time] [%FuncShort @ %File.%Line] %Msg%n"/>
        <format id="all" format="[%Level] [%Time] [@ %File.%Line] %Msg%n"/>
        <format id="criticalemail" format="Critical error on our server!\n    %Time %Date %RelFile %Func %Msg \nSent by Seelog"/>
    </formats>
</seelog>

Then we build the customized module like this
>go build src/com/sillycat/easygoapp/logs/LogCustom.go

Then I can use it like this>
package main

import (
     "com/sillycat/easygoapp/logs"
)

func main() {
     addr := "locahost"
     logs.Logger.Info("Start server at:", addr)
     err := "Fail to start the server."
     logs.Logger.Critical("Server err:", err)
}

This is the right way how we can manage our modules and codes in our own projects.

References:
https://github.com/astaxie/build-web-application-with-golang/blob/master/ebook/11.1.md
https://github.com/astaxie/build-web-application-with-golang/blob/master/ebook/11.2.md

https://github.com/astaxie/build-web-application-with-golang/blob/master/ebook/11.3.md

https://github.com/cihub/seelog

http://godoc.org/github.com/cihub/seelog


你可能感兴趣的:(logging)