在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ GO/ 13.4 日志和配置設計
7 文本處理
3 Web基礎
14 擴展Web框架
10.4 小結
2.2 Go基礎
2.8 總結
6.1 session和cookie
5.5 使用beedb庫進行ORM開發(fā)
8.3 REST
13.6 小結
5.4 使用PostgreSQL數據庫
14.6 pprof支持
14.1 靜態(tài)文件支持
11.2 使用GDB調試
7.7 小結
1 GO環(huán)境配置
14.5 多語言支持
7.1 XML處理
1.5 總結
13 如何設計一個Web框架
14.3 表單及驗證支持
12 部署與維護
10 國際化和本地化
1.1 Go 安裝
6.2 Go如何使用session
5.6 NOSQL數據庫操作
6.5 小結
9.4 避免SQL注入
12.1 應用日志
4.2 驗證表單的輸入
10.1 設置默認地區(qū)
1.3 Go 命令
9.6 加密和解密數據
4.1 處理表單的輸入
4.4 防止多次遞交表單
11.3 Go怎么寫測試用例
8 Web服務
12.3 應用部署
5.7 小結
12.5 小結
11 錯誤處理,調試和測試
9.2 確保輸入過濾
14.2 Session支持
6.4 預防session劫持
12.4 備份和恢復
8.1 Socket編程
13.1 項目規(guī)劃
13.4 日志和配置設計
7.6 字符串處理
13.2 自定義路由器設計
6.3 session存儲
3.4 Go的http包詳解
8.2 WebSocket
10.3 國際化站點
7.5 文件操作
7.4 模板處理
9.1 預防CSRF攻擊
13.3 controller設計
2.6 interface
14.4 用戶認證
2.3 流程和函數
附錄A 參考資料
11.1 錯誤處理
9.5 存儲密碼
9.3 避免XSS攻擊
12.2 網站錯誤處理
6 session和數據存儲
2.4 struct類型
3.3 Go如何使得Web工作
2.5 面向對象
3.1 Web工作方式
1.2 GOPATH與工作空間
2.1 你好,Go
9.7 小結
13.5 實現博客的增刪改
7.2 JSON處理
10.2 本地化資源
7.3 正則處理
2 Go語言基礎
5.1 database/sql接口
4.5 處理文件上傳
8.5 小結
4.3 預防跨站腳本
5.3 使用SQLite數據庫
14.7 小結
3.2 Go搭建一個Web服務器
2.7 并發(fā)
5 訪問數據庫
4 表單
3.5 小結
1.4 Go開發(fā)工具
11.4 小結
9 安全與加密
5.2 使用MySQL數據庫
4.6 小結
8.4 RPC

13.4 日志和配置設計

日志和配置的重要性

前面已經介紹過日志在我們程序開發(fā)中起著很重要的作用,通過日志我們可以記錄調試我們的信息,當初介紹過一個日志系統seelog,根據不同的level輸出不同的日志,這個對于程序開發(fā)和程序部署來說至關重要。我們可以在程序開發(fā)中設置level低一點,部署的時候把level設置高,這樣我們開發(fā)中的調試信息可以屏蔽掉。

配置模塊對于應用部署牽涉到服務器不同的一些配置信息非常有用,例如一些數據庫配置信息、監(jiān)聽端口、監(jiān)聽地址等都是可以通過配置文件來配置,這樣我們的應用程序就具有很強的靈活性,可以通過配置文件的配置部署在不同的機器上,可以連接不同的數據庫之類的。

beego的日志設計

beego的日志設計部署思路來自于seelog,根據不同的level來記錄日志,但是beego設計的日志系統比較輕量級,采用了系統的log.Logger接口,默認輸出到os.Stdout,用戶可以實現這個接口然后通過beego.SetLogger設置自定義的輸出,詳細的實現如下所示:

// Log levels to control the logging output.
const (
    LevelTrace = iota
    LevelDebug
    LevelInfo
    LevelWarning
    LevelError
    LevelCritical
)

// logLevel controls the global log level used by the logger.
var level = LevelTrace

// LogLevel returns the global log level and can be used in
// own implementations of the logger interface.
func Level() int {
    return level
}

// SetLogLevel sets the global log level used by the simple
// logger.
func SetLevel(l int) {
    level = l
}

上面這一段實現了日志系統的日志分級,默認的級別是Trace,用戶通過SetLevel可以設置不同的分級。

// logger references the used application logger.
var BeeLogger = log.New(os.Stdout, "", log.Ldate|log.Ltime)

// SetLogger sets a new logger.
func SetLogger(l *log.Logger) {
    BeeLogger = l
}

// Trace logs a message at trace level.
func Trace(v ...interface{}) {
    if level <= LevelTrace {
        BeeLogger.Printf("[T] %v\n", v)
    }
}

// Debug logs a message at debug level.
func Debug(v ...interface{}) {
    if level <= LevelDebug {
        BeeLogger.Printf("[D] %v\n", v)
    }
}

// Info logs a message at info level.
func Info(v ...interface{}) {
    if level <= LevelInfo {
        BeeLogger.Printf("[I] %v\n", v)
    }
}

// Warning logs a message at warning level.
func Warn(v ...interface{}) {
    if level <= LevelWarning {
        BeeLogger.Printf("[W] %v\n", v)
    }
}

// Error logs a message at error level.
func Error(v ...interface{}) {
    if level <= LevelError {
        BeeLogger.Printf("[E] %v\n", v)
    }
}

// Critical logs a message at critical level.
func Critical(v ...interface{}) {
    if level <= LevelCritical {
        BeeLogger.Printf("[C] %v\n", v)
    }
}

上面這一段代碼默認初始化了一個BeeLogger對象,默認輸出到os.Stdout,用戶可以通過beego.SetLogger來設置實現了logger的接口輸出。這里面實現了六個函數:

  • Trace(一般的記錄信息,舉例如下:)
    • "Entered parse function validation block"
    • "Validation: entered second 'if'"
    • "Dictionary 'Dict' is empty. Using default value"
  • Debug(調試信息,舉例如下:)
    • "Web page requested: http://somesite.com Params='...'"
    • "Response generated. Response size: 10000. Sending."
    • "New file received. Type:PNG Size:20000"
  • Info(打印信息,舉例如下:)
    • "Web server restarted"
    • "Hourly statistics: Requested pages: 12345 Errors: 123 ..."
    • "Service paused. Waiting for 'resume' call"
  • Warn(警告信息,舉例如下:)
    • "Cache corrupted for file='test.file'. Reading from back-end"
    • "Database 192.168.0.7/DB not responding. Using backup 192.168.0.8/DB"
    • "No response from statistics server. Statistics not sent"
  • Error(錯誤信息,舉例如下:)
    • "Internal error. Cannot process request #12345 Error:...."
    • "Cannot perform login: credentials DB not responding"
  • Critical(致命錯誤,舉例如下:)
    • "Critical panic received: .... Shutting down"
    • "Fatal error: ... App is shutting down to prevent data corruption or loss"

可以看到每個函數里面都有對level的判斷,所以如果我們在部署的時候設置了level=LevelWarning,那么Trace、Debug、Info這三個函數都不會有任何的輸出,以此類推。

beego的配置設計

配置信息的解析,beego實現了一個key=value的配置文件讀取,類似ini配置文件的格式,就是一個文件解析的過程,然后把解析的數據保存到map中,最后在調用的時候通過幾個string、int之類的函數調用返回相應的值,具體的實現請看下面:

首先定義了一些ini配置文件的一些全局性常量 :

var (
    bComment = []byte{'#'}
    bEmpty   = []byte{}
    bEqual   = []byte{'='}
    bDQuote  = []byte{'"'}
)

定義了配置文件的格式:

// A Config represents the configuration.
type Config struct {
    filename string
    comment  map[int][]string  // id: []{comment, key...}; id 1 is for main comment.
    data     map[string]string // key: value
    offset   map[string]int64  // key: offset; for editing.
    sync.RWMutex
}

定義了解析文件的函數,解析文件的過程是打開文件,然后一行一行的讀取,解析注釋、空行和key=value數據:

// ParseFile creates a new Config and parses the file configuration from the
// named file.
func LoadConfig(name string) (*Config, error) {
    file, err := os.Open(name)
    if err != nil {
        return nil, err
    }

    cfg := &Config{
        file.Name(),
        make(map[int][]string),
        make(map[string]string),
        make(map[string]int64),
        sync.RWMutex{},
    }
    cfg.Lock()
    defer cfg.Unlock()
    defer file.Close()

    var comment bytes.Buffer
    buf := bufio.NewReader(file)

    for nComment, off := 0, int64(1); ; {
        line, _, err := buf.ReadLine()
        if err == io.EOF {
            break
        }
        if bytes.Equal(line, bEmpty) {
            continue
        }

        off += int64(len(line))

        if bytes.HasPrefix(line, bComment) {
            line = bytes.TrimLeft(line, "#")
            line = bytes.TrimLeftFunc(line, unicode.IsSpace)
            comment.Write(line)
            comment.WriteByte('\n')
            continue
        }
        if comment.Len() != 0 {
            cfg.comment[nComment] = []string{comment.String()}
            comment.Reset()
            nComment++
        }

        val := bytes.SplitN(line, bEqual, 2)
        if bytes.HasPrefix(val[1], bDQuote) {
            val[1] = bytes.Trim(val[1], `"`)
        }

        key := strings.TrimSpace(string(val[0]))
        cfg.comment[nComment-1] = append(cfg.comment[nComment-1], key)
        cfg.data[key] = strings.TrimSpace(string(val[1]))
        cfg.offset[key] = off
    }
    return cfg, nil
}

下面實現了一些讀取配置文件的函數,返回的值確定為bool、int、float64或string:

// Bool returns the boolean value for a given key.
func (c *Config) Bool(key string) (bool, error) {
    return strconv.ParseBool(c.data[key])
}

// Int returns the integer value for a given key.
func (c *Config) Int(key string) (int, error) {
    return strconv.Atoi(c.data[key])
}

// Float returns the float value for a given key.
func (c *Config) Float(key string) (float64, error) {
    return strconv.ParseFloat(c.data[key], 64)
}

// String returns the string value for a given key.
func (c *Config) String(key string) string {
    return c.data[key]
}

應用指南

下面這個函數是我一個應用中的例子,用來獲取遠程url地址的json數據,實現如下:

func GetJson() {
    resp, err := http.Get(beego.AppConfig.String("url"))
    if err != nil {
        beego.Critical("http get info error")
        return
    }
    defer resp.Body.Close()
    body, err := ioutil.ReadAll(resp.Body)
    err = json.Unmarshal(body, &AllInfo)
    if err != nil {
        beego.Critical("error:", err)
    }
}

函數中調用了框架的日志函數beego.Critical函數用來報錯,調用了beego.AppConfig.String("url")用來獲取配置文件中的信息,配置文件的信息如下(app.conf):

appname = hs
url ="http://www.api.com/api.html"