1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢(xún)
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時(shí)間:8:30-17:00
      你可能遇到了下面的問(wèn)題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷(xiāo)解決方案
      Go語(yǔ)言11-日志系統(tǒng)客戶(hù)端相關(guān)組件

      tailf 組件

      查看log日志,會(huì)經(jīng)常使用到tail -f命令實(shí)時(shí)跟蹤文件變化。也可以用Go語(yǔ)言的代碼來(lái)實(shí)現(xiàn)同樣的功能,這樣就可以直接用到項(xiàng)目中去了。這里不用重復(fù)造輪子,有一個(gè)第三方的庫(kù)已經(jīng)實(shí)現(xiàn)了這個(gè)功能:

      成都一家集口碑和實(shí)力的網(wǎng)站建設(shè)服務(wù)商,擁有專(zhuān)業(yè)的企業(yè)建站團(tuán)隊(duì)和靠譜的建站技術(shù),十多年企業(yè)及個(gè)人網(wǎng)站建設(shè)經(jīng)驗(yàn) ,為成都成百上千家客戶(hù)提供網(wǎng)頁(yè)設(shè)計(jì)制作,網(wǎng)站開(kāi)發(fā),企業(yè)網(wǎng)站制作建設(shè)等服務(wù),包括成都營(yíng)銷(xiāo)型網(wǎng)站建設(shè),品牌網(wǎng)站制作,同時(shí)也為不同行業(yè)的客戶(hù)提供網(wǎng)站制作、成都網(wǎng)站設(shè)計(jì)的服務(wù),包括成都電商型網(wǎng)站制作建設(shè),裝修行業(yè)網(wǎng)站制作建設(shè),傳統(tǒng)機(jī)械行業(yè)網(wǎng)站建設(shè),傳統(tǒng)農(nóng)業(yè)行業(yè)網(wǎng)站制作建設(shè)。在成都做網(wǎng)站,選網(wǎng)站制作建設(shè)服務(wù)商就選創(chuàng)新互聯(lián)公司

      import "github.com/hpcloud/tail"

      HP團(tuán)隊(duì)出的tail庫(kù),常用于日志收集。這里主要就是看看如何使用。

      示例代碼

      package main
      
      import (
          "os"
          "fmt"
          "github.com/hpcloud/tail"
          "time"
      )
      
      func main () {
          filename := "tailf_test.txt"  // 指定查看哪個(gè)文件
          tails, err := tail.TailFile(filename, tail.Config{
              // 下面的2行配置,相當(dāng)于命令 tail -F 的效果
              // 追蹤文件并保持重試,即該文件被刪除或改名后,如果再次創(chuàng)建相同的文件名,會(huì)繼續(xù)追蹤。
              ReOpen: true,
              Follow: true,
      
              Location: &tail.SeekInfo{Offset: 0, Whence: os.SEEK_END},  // 從哪個(gè)位置開(kāi)始讀,這里的設(shè)置是從文件結(jié)尾
              MustExist: false,  // 如果文件不存在,會(huì)失敗。這是設(shè)為fales,允許文件不存在,等文件一創(chuàng)建就會(huì)開(kāi)始追蹤
              Poll: true,  // 設(shè)為true,檢查文件的變化。false是通過(guò)inotify來(lái)檢查
          })
          if err != nil {
              fmt.Fprintf(os.Stderr, "tail file: %s , ERROR: %v\n", tails.Filename, err)
          }
          for {
              msg, ok := <-tails.Lines
              if ! ok {
                  fmt.Fprintf(os.Stderr, "文件不存在,嘗試重新打開(kāi)文件: %s", tails.Filename)
                  time.Sleep(time.Millisecond * 1000)
                  continue
              }
              fmt.Println("msg:", msg.Text)
              fmt.Println("time:", msg.Time)
              // windows系統(tǒng)里的換行是\r\n,輸出的時(shí)候可能只去掉了\n,導(dǎo)致字符串會(huì)以\r結(jié)尾
              // 如果以\r結(jié)尾,后面還有字符串的話,就會(huì)從頭開(kāi)始把之前的內(nèi)容覆蓋掉
              fmt.Printf("%q\n", msg.Text)  // 輸出有問(wèn)題的原因是這樣的,這里可以看出來(lái)
              // 可以手動(dòng)把 msg.Text 最后的 \r 去掉,即使沒(méi)有,也不影響
              fmt.Printf("msg: %s time: %s\n", strings.TrimRight(msg.Text, "\r"), msg.Time)
          }
      }

      這里最后踩了個(gè)小坑,應(yīng)該是windows系統(tǒng)才會(huì)有的問(wèn)題。

      配置文件庫(kù)

      解析配置文件使用的第三方庫(kù)是屬于beego框架里的一個(gè)模塊。

      beego 框架

      beego是一個(gè)快速開(kāi)發(fā)Go應(yīng)用的HTTP框架,他可以用來(lái)快速開(kāi)發(fā)API、Web及后端服務(wù)等各種應(yīng)用,是一個(gè) RESTful的框架。
      安裝:

      go get github.com/astaxie/beego

      beego是基于八大獨(dú)立的模塊構(gòu)建的,是一個(gè)高度解耦的框架:

      • cache : 做緩存
      • config : 解析各種格式的配置文件
      • context
      • httplibs
      • logs : 記錄操作信息
      • orm
      • session
      • toolbox

      接下來(lái)只是單獨(dú)把某個(gè)模塊拿來(lái)使用,不學(xué)習(xí)框架的使用。安裝的話只能完整的全部裝上了。

      使用示例

      基本用法:
      配置文件如下:

      [server]
      host = "1.1.1.1"
      port = 23

      示例代碼:

      package main
      
      import (
          "github.com/astaxie/beego/config"
          "fmt"
          "os"
      )
      
      func main() {
          conf, err := config.NewConfig("ini", "test.conf")  // 配置文件格式和文件路徑
          if err != nil {
              fmt.Fprintf(os.Stderr, "New Confit ERROR: %v\n", err)
              return
          }
          port, err := conf.Int("server::port")  // 獲取數(shù)值型數(shù)據(jù)可能會(huì)返回錯(cuò)誤
          if err != nil {
              fmt.Fprintf(os.Stderr, "get conf ERROR: %v\n", err)
              return
          }
          fmt.Println("port:", port)
          host := conf.String("server::host")  // 獲取字符串?dāng)?shù)據(jù),不會(huì)返回錯(cuò)誤,讀不到會(huì)返回空字符串
          fmt.Println("host:", host)
          ip := conf.String("server::ip")  // 讀不到就會(huì)返回空
          fmt.Println("ip:", ip)
          ip2 := conf.DefaultString("server::ip", "1.1.1.2")  // 代碼層面指定的默認(rèn)值
          fmt.Println("ip2", ip2)
      }

      默認(rèn)值
      上面的默認(rèn)值是在代碼層面實(shí)現(xiàn)的。但是ini配置本身是支持默認(rèn)值的,定義的時(shí)候可以寫(xiě)在最外面,也可以寫(xiě)在[default] 里面,效果都是一樣的:

      key1 = vale1
      
      [default]
      key2 = value2
      
      [server]
      host = "1.1.1.1"
      port = 23
      key1 = v1

      示例代碼:

      package main
      
      import (
          "github.com/astaxie/beego/config"
          "fmt"
          "os"
      )
      
      func main() {
          conf, err := config.NewConfig("ini", "test.conf")  // 配置文件格式和文件路徑
          if err != nil {
              fmt.Fprintf(os.Stderr, "New Confit ERROR: %v\n", err)
              return
          }
          server, err := conf.GetSection("server")  // 可以獲取到所有的參數(shù),返回map
          if err != nil {
              fmt.Fprintf(os.Stderr, "get section ERROR: %v\n", err)
          }
          fmt.Println(server)
          df, err := conf.GetSection("default")  // default里的以及最外層的參數(shù)都會(huì)解析存到這個(gè)map里
          if err != nil {
              fmt.Fprintf(os.Stderr, "get section ERROR: %v\n", err)
          }
          fmt.Println(df)
      
          key1a, key1b := conf.String("key1"), conf.String("default::key1")  //  前面是否加上 default:: 都是一樣的
          key2 := conf.String("key2")
          fmt.Println(key1a, key1b, key2)
          // 解析獲取默認(rèn)值可能就是這么做的吧,網(wǎng)上沒(méi)有找到相關(guān)的示例
          k1 := conf.DefaultString("server::key1", conf.String("key1"))
          k2 := conf.DefaultString("server::key2", conf.String("key2"))
          fmt.Println(k1, k2)
      }

      日志庫(kù)

      這個(gè)還是beego框架里的一個(gè)組件

      基本使用

      先把log輸出到終端:

      package main
      
      import (
          "github.com/astaxie/beego/logs"
      )
      
      func main() {
          logs.SetLogger(logs.AdapterConsole)  // 設(shè)置日志輸出到哪里, 參數(shù)是個(gè)常數(shù)。這里的效果是輸出到終端
          logs.SetLevel(logs.LevelInfo)  // 設(shè)置日志等級(jí)
          logs.Debug("DEBUG msg")  // 這條等級(jí)不夠,不會(huì)顯示
          logs.Info("INFO msg")
      }

      這里使用了console引擎,就是輸出到終端,底層是到os.Stdout。

      輸出到文件

      要把log輸出到文件,只需要設(shè)置一個(gè)新的file引擎:

      package main
      
      import (
          "github.com/astaxie/beego/logs"
      )
      
      func main() {
          logs.SetLogger(logs.AdapterFile, `{"filename":"test.log","level":6}`)  // logs.LevelInfo = 6
          logs.SetLogger(logs.AdapterConsole, `{"level":4,"?color":true}`)  // logs.LevelWarning = 4
          logs.SetLevel(logs.LevelInfo)
          logs.Info("INFO msg")
          logs.Warn("WARN msg")
      }

      SetLogger接收2個(gè)參數(shù)。
      第一個(gè)參數(shù)就是引擎名,這里用到了2個(gè) "console" 和 "file" 。上面的代碼里寫(xiě)的是常量名。
      第二個(gè)參數(shù)是可選參數(shù)(上個(gè)例子沒(méi)有用,這里都用上了),用來(lái)表示配置信息,所有配置寫(xiě)在一個(gè)json字符串里。

      更多引擎和參數(shù)

      這里可參考官網(wǎng)的引擎配置設(shè)置:
      https://beego.me/docs/module/logs.md

      這里只列出2個(gè)
      console 主要參數(shù)說(shuō)明:

      • level 輸出的日志級(jí)別
      • color 是否開(kāi)啟打印日志彩色打印(需環(huán)境支持彩色輸出)

      file 主要參數(shù)說(shuō)明:

      • filename 保存的文件名
      • maxlines 每個(gè)文件保存的最大行數(shù),默認(rèn)值 1000000
      • maxsize 每個(gè)文件保存的最大尺寸,默認(rèn)值是 1 << 28, //256 MB
      • daily 是否按照每天 logrotate,默認(rèn)是 true
      • maxdays 文件最多保存多少天,默認(rèn)保存 7 天
      • rotate 是否開(kāi)啟 logrotate,默認(rèn)是 true
      • level 日志保存的時(shí)候的級(jí)別,默認(rèn)是 Trace 級(jí)別
      • perm 日志文件權(quán)限

      所有的引擎有這些,左邊是常量,右邊是對(duì)應(yīng)的名字:

      const (
          AdapterConsole   = "console"
          AdapterFile      = "file"
          AdapterMultiFile = "multifile"
          AdapterMail      = "smtp"
          AdapterConn      = "conn"
          AdapterEs        = "es"
          AdapterJianLiao  = "jianliao"
          AdapterSlack     = "slack"
          AdapterAliLS     = "alils"
      )

      注冊(cè)引擎名

      所有的引擎,都會(huì)自動(dòng)進(jìn)行注冊(cè)。具體就是寫(xiě)在引擎的代碼的init方法里:

      // beego/logs/console.go
      func init() {
          Register(AdapterConsole, NewConsole)
      }

      不過(guò)很多太多方法都是小寫(xiě)的,導(dǎo)致接口沒(méi)有暴露出來(lái)用不了。只有 console 和 conn 引擎可以注冊(cè)。

      package main
      
      import (
          "github.com/astaxie/beego/logs"
          "encoding/json"
          "fmt"
          "os"
      )
      
      func main() {
          logs.Register("new", logs.NewConsole)
          config := make(map[string]interface{})  // 先定義一個(gè)map來(lái)存放配置參數(shù)
          config["level"] = 4  // LevelWarning = 4
          config["color"] = true  // map的value可能是字符串、×××或bool等不同的類(lèi)型,所以定義的時(shí)候類(lèi)型是空接口
          configStr, err := json.Marshal(config)
          if err != nil {
              fmt.Fprintf(os.Stderr, "json Marshal ERROR %v\n", err)
              return
          }
          logs.SetLogger("new", string(configStr))  // 用map來(lái)設(shè)置參數(shù),到這里再轉(zhuǎn)成json字符串
          logs.SetLogger(logs.AdapterConsole)  // 再設(shè)置一個(gè)默認(rèn)的console引擎
          logs.Info("INFO msg")  // 滿(mǎn)足1個(gè)logger
          logs.Error("ERROR msg")  // 兩個(gè)logger都會(huì)輸出這條
      }

      使用map來(lái)設(shè)置配置信息
      配置信息是要傳遞json字符串進(jìn)去的,但是人工拼接josn也是很不友好的。所以先把配置寫(xiě)在map里,然后再序列化成json傳遞給函數(shù)。并且map的value是空接口,因?yàn)榕渲每赡苁亲址⒄麛?shù)或布爾等不同類(lèi)型。
      無(wú)法注冊(cè)file引擎
      注冊(cè)不了新的file引擎貌似沒(méi)啥用。源碼沒(méi)有把對(duì)應(yīng)的方法暴露出來(lái)應(yīng)該就沒(méi)有辦法了,就是 func newFileWriter() Logger{} 這個(gè)函數(shù),函數(shù)名是小寫(xiě)的。只能去改源碼,還不方便把上面的函數(shù)名改掉,因?yàn)樵趧e處還有調(diào)用這個(gè)方法。所以最方便的修改方法是給原來(lái)的小寫(xiě)的函數(shù)名定義一個(gè)大寫(xiě)的別名:

      func newFileWriter() Logger {
          // 省略函數(shù)體部分
      }
      
      var NewFileWriter func() Logger = newFileWriter

      如果代碼中有這種需要開(kāi)放接口,又不想修改每一個(gè)被應(yīng)用的位置,可以用上面的例子來(lái)把接口變成可導(dǎo)出的。

      多文件的正確用法
      沒(méi)有提供注冊(cè)file引擎的接口,是因?yàn)檩敵龅蕉鄠€(gè)文件還提供了另外一個(gè)multifile的引擎。之前只把注意力集中到了file引擎上,沒(méi)有發(fā)現(xiàn)還有其他的可用的引擎。
      雖然multifile底層也是通過(guò)調(diào)用file來(lái)實(shí)現(xiàn)的,是在file的基礎(chǔ)上又做了一些封裝。所以如果需要輸出到多個(gè)文件,應(yīng)該使用提供的multifile來(lái)實(shí)現(xiàn)。


      分享題目:Go語(yǔ)言11-日志系統(tǒng)客戶(hù)端相關(guān)組件
      網(wǎng)站路徑:http://www.ef60e0e.cn/article/pghiph.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        乌拉特前旗| 五河县| 安丘市| 海安县| 邯郸市| 兴国县| 潞城市| 鹤峰县| 房产| 旌德县| 麟游县| 定远县| 苏尼特右旗| 土默特左旗| 天祝| 兴安县| 遂平县| 沧源| 三门峡市| 内江市| 兰考县| 丁青县| 华安县| 通海县| 浠水县| 济源市| 镇赉县| 抚顺县| 巩留县| 湖北省| 彰化县| 南涧| 卫辉市| 丁青县| 万盛区| 莎车县| 敖汉旗| 湾仔区| 同仁县| 武鸣县| 北票市|