当前位置: 首页 > news >正文

网站排名怎么做 知乎最近军事新闻

网站排名怎么做 知乎,最近军事新闻,做英文网站多少钱,go 语言 做网站文章目录 本文目标新建logging包file.go编写log文件当前目录结构 接入自定义的log功能验证功能 本文目标 在上一节中,我们解决了 API’s 可以任意访问的问题,那么我们现在还有一个问题,就是我们的日志,都是输出到控制台上的&…

文章目录

  • 本文目标
  • 新建`logging`包
    • file.go
    • 编写log文件
    • 当前目录结构
  • 接入自定义的log功能
  • 验证功能

本文目标

在上一节中,我们解决了 API’s 可以任意访问的问题,那么我们现在还有一个问题,就是我们的日志,都是输出到控制台上的,这显然对于一个项目来说是不合理的,因此我们这一节简单封装log库,使其支持简单的文件日志!

新建logging

我们在pkg下新建logging目录,用来包含自定义logger相关的文件,新建file.golog.go文件

file.go

用来创建记录log的相关目录和文件,其内容为:

package loggingimport ("fmt""log""os""time"
)// 适用枚举,将所有固定的量提前列出在这里,方便后期维护	我们这里将原来的var修改为const
const (LogSavePath = "runtime/logs/"LogSaveName = "log"LogFileExt  = "log"TimeFormat  = "20060102"
)// 返回log文件的前缀路径,算是一个具有仪式感的函数
func getLogFilePath() string {return fmt.Sprintf("%s", LogSavePath)
}// 获得log文件的整体路径,以当前日期作为.log文件的名字
func getLogFileFullPath() string {prefixPath := getLogFilePath()suffixPath := fmt.Sprintf("%s%s.%s", LogSaveName, time.Now().Format(TimeFormat), LogFileExt)return fmt.Sprintf("%s%s", prefixPath, suffixPath)
}// 打开日志文件,返回写入的句柄handle
func openLogFile(filePath string) *os.File {//根据文件目录是否存在进行判断_, err := os.Stat(filePath)switch {//目录不存在case os.IsNotExist(err):mkDir()//权限不够case os.IsPermission(err):log.Fatalf("Permission :%v", err)}//如果.log文件不存在,这里会创建一个handle, err := os.OpenFile(filePath, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)if err != nil {log.Fatalf("Fail to OpenFile :%v", err)}return handle
}// 创建log目录
func mkDir() {//获得当前目录 dir: /home/wang2/gin-exampledir, _ := os.Getwd()//适用MKdirAll会直接创建所有依赖的父目录,减少报错的可能性err := os.MkdirAll(dir+"/"+getLogFilePath(), os.ModePerm)if err != nil {panic(err)}
}
  • os.Stat:返回文件信息结构描述文件。如果出现错误,会返回*PathError
    type PathError struct {Op   stringPath stringErr  error
    }
    
  • os.IsNotExist:能够接受ErrNotExistsyscall的一些错误,它会返回一个布尔值,能够得知文件不存在或目录不存在
  • os.IsPermission:能够接受ErrPermissionsyscall的一些错误,它会返回一个布尔值,能够得知权限是否满足
  • os.OpenFile:调用文件,支持传入文件名称、指定的模式调用文件、文件权限,返回的文件的方法可以用于 I/O。如果出现错误,则为*PathError
    const (// Exactly one of O_RDONLY, O_WRONLY, or O_RDWR must be specified.O_RDONLY int = syscall.O_RDONLY // 以只读模式打开文件O_WRONLY int = syscall.O_WRONLY // 以只写模式打开文件O_RDWR   int = syscall.O_RDWR   // 以读写模式打开文件// The remaining values may be or'ed in to control behavior.O_APPEND int = syscall.O_APPEND // 在写入时将数据追加到文件中O_CREATE int = syscall.O_CREAT  // 如果不存在,则创建一个新文件O_EXCL   int = syscall.O_EXCL   // 使用O_CREATE时,文件必须不存在O_SYNC   int = syscall.O_SYNC   // 同步IOO_TRUNC  int = syscall.O_TRUNC  // 如果可以,打开时
    )
    
  • os.Getwd:返回与当前目录对应的根路径名
  • os.MkdirAll:创建对应的目录以及所需的子目录,若成功则返回nil,否则返回error
  • os.ModePermconst定义ModePerm FileMode = 0777

文件权限的知识补充:err := os.MkdirAll(“wang2/”+path, os.ModePerm)
这里的modePerm中Perm为permission的缩写
在Linux和Unix操作系统中,文件和目录的权限通常用八进制数表示,例如 0777。这个八进制数表示了文件或目录的权限位,以及哪些用户或用户组有权访问它。在 0777 中,每一位都有特定的含义:

  • 最高位(左边的0)表示特殊权限位,通常不使用,所以它通 常是0。
  • 下一个三位(中间的777)表示用户(文件的所有者)的权限。
  • 接下来的三位表示组(文件的所属组)的权限。
  • 最后三位表示其他人(不是文件所有者或所属组的用户)的权限。

每个三位权限位由三个位组成,它们可以是以下之一:

  • 4:读权限(R):用户可以读取文件或列出目录中的内容。
  • 2:写权限(W):用户可以编辑或写入文件,对于目录来说,用户可以在其中创建、删除或重命名文件。
  • 1:执行权限(X):用户可以执行文件或进入目录。

编写log文件

log.go:

package loggingimport ("fmt""log""os""path/filepath""runtime"
)// 类型声明,基于int建立level,方便后续维护
type Level intvar (//传入写log文件的句柄F *os.File//默认的前缀DefaultPrefix = ""//这里的定义在后续的caller中被调用,该参数指定了要跳过的调用堆栈帧数,每个调用堆栈帧代表了代码中的一个函数调用。//以info写入log为例,我们这里调用caller的函数为setPrefix,Info调用setPrefix,适用Info进行写入的函数调用info。//                                     0                      1                    2//而我们想要得到的信息就是调用info的函数的信息。所以我们这里设置的跳过调用堆栈帧数为2DefaultCallerDepth = 2//提前定义logger记录器,方便维护阅读logger *log.LoggerlogPrefix = ""//结合level的定义,方便读取维护levelFlags = []string{"DEBUG", "INFO", "WARN", "ERROR", "FATAL"}
)// 实现枚举
const (DEBUG Level = iotaINFOWARNINGERRORFATAL
)// 自定义logger的初始化
func init() {//获取log文件目录filePath := getLogFileFullPath()//得到log文件句柄F = openLogFile(filePath)//创建一个新的日志记录器logger = log.New(F, DefaultPrefix, log.LstdFlags)
}func Debug(v ...interface{}) {setPrefix(DEBUG)logger.Println(v)
}// 这里先设置每条log的前缀部分,首先为log模式,这里为info;然后为具体到某个函数第几行出错;接下来为时间;最后为日志信息
func Info(v ...interface{}) {setPrefix(INFO)logger.Println(v)
}func Warn(v ...interface{}) {setPrefix(WARNING)logger.Println(v)
}func Error(v ...interface{}) {setPrefix(ERROR)logger.Println(v)
}func Fatal(v ...interface{}) {setPrefix(FATAL)logger.Fatalln(v)
}// 从进程中读取当前运行的函数信息
func setPrefix(level Level) {//获取文件名,具体行数,是否读取成功_, file, line, ok := runtime.Caller(DefaultCallerDepth)if ok { //获取成功logPrefix = fmt.Sprintf("[%s][%s:%d]", levelFlags[level], filepath.Base(file), line)} else { //获取失败,则前缀不加如具体的文件名和行号logPrefix = fmt.Sprintf("[%s]", levelFlags[level])}//将前缀写入log文件logger.SetPrefix(logPrefix)
}
  • log.New:创建一个新的日志记录器。out定义要写入日志数据的IO句柄。prefix定义每个生成的日志行的开头。flag定义了日志记录属性
    func New(out io.Writer, prefix string, flag int) *Logger {return &Logger{out: out, prefix: prefix, flag: flag}
    }
    
  • log.LstdFlags:日志记录的格式属性之一,其余的选项如下
    const (Ldate         = 1 << iota     // the date in the local time zone: 2009/01/23Ltime                         // the time in the local time zone: 01:23:23Lmicroseconds                 // microsecond resolution: 01:23:23.123123.  assumes Ltime.Llongfile                     // full file name and line number: /a/b/c/d.go:23Lshortfile                    // final file name element and line number: d.go:23. overrides LlongfileLUTC                          // if Ldate or Ltime is set, use UTC rather than the local time zoneLstdFlags     = Ldate | Ltime // initial values for the standard logger
    )
    

当前目录结构

gin-blog/
├── conf
│   └── app.ini
├── main.go
├── middleware
│   └── jwt
│       └── jwt.go
├── models
│   ├── article.go
│   ├── auth.go
│   ├── models.go
│   └── tag.go
├── pkg
│   ├── e
│   │   ├── code.go
│   │   └── msg.go
│   ├── logging
│   │   ├── file.go
│   │   └── log.go
│   ├── setting
│   │   └── setting.go
│   └── util
│       ├── jwt.go
│       └── pagination.go
├── routers
│   ├── api
│   │   ├── auth.go
│   │   └── v1
│   │       ├── article.go
│   │       └── tag.go
│   └── router.go
├── runtime

接入自定义的log功能

我们自定义的logging包,已经基本完成了,接下来让它接入到我们的项目之中吧。我们打开先前包含log包的代码,如下:

  1. 打开routers目录下的article.gotag.goauth.go
    2。 将log包的引用删除,修改引用我们自己的日志包为github.com/kingsill/gin-example/pkg/logging
  2. 将原本的log.Println(...)改为logging.Info(...)

验证功能

修改文件后,重启服务,我们来试试吧!

获取到 APIToken 后,我们故意传错误 URL 参数给接口,如:http://127.0.0.1:8000/api/v1/articles?tag_id=0&state=9999999&token=eyJhbG..

然后我们到$GOPATH/gin-blog/runtime/logs查看日志:

$ tail -f log20180216.log
[INFO][article.go:79]2018/02/16 18:33:12 [state 状态只允许0或1]
[INFO][article.go:79]2018/02/16 18:33:42 [state 状态只允许0或1]
[INFO][article.go:79]2018/02/16 18:33:42 [tag_id 标签ID必须大于0]
[INFO][article.go:79]2018/02/16 18:38:39 [state 状态只允许0或1]
[INFO][article.go:79]2018/02/16 18:38:39 [tag_id 标签ID必须大于0]

日志结构一切正常,我们的记录模式都为Info,因此前缀是对的,并且我们是入参有问题,也把错误记录下来了,这样排错就很方便了!

至此,本节就完成了,这只是一个简单的扩展,实际上我们线上项目要使用的文件日志,是更复杂一些,开动你的大脑 举一反三吧!

http://www.zhongyajixie.com/news/3395.html

相关文章:

  • 农安县建设局官方网站seo优化在线
  • 静态网页建站关键词排名优化易下拉技巧
  • 武汉有没有做网站的西安排名seo公司
  • 网站制作公司 信科网络直播营销
  • 网站建设制作视频教程汕头seo排名
  • 专做餐饮的网站3a汽车集团公司网络营销方案
  • 免费网站后台管理模板下载百度不收录网站怎么办
  • 网站开发面试内容东莞网站推广公司黄页
  • 网站开发禁止下载功能黑帽seo论坛
  • wordpress4.x下载seo综合查询是什么
  • 靖江网站建设市场调研方案范文
  • 做网站外包需要提供什么百度手机网页
  • 苏州市建设局网站下载百度导航app
  • 做景观素材有哪几个网站绍兴seo推广公司
  • 临汾网站建设 吕梁网站建设石家庄网站建设
  • 做外贸的网站有何用处深圳关键词推广排名
  • 襄阳手机网站建设公司最有效的线上推广方式
  • 做水电到哪个网站找信息百度引擎搜索入口
  • 上海工商注册公司代办河北seo技术培训
  • 最牛html5网站建设品牌营销策划案例
  • 在线旅游网站建设前的调研淘宝seo优化是什么
  • 什么是网站分析东莞seo优化团队
  • 增城有什么网站做招聘的品牌推广是做什么的
  • 单页营销型网站怎么查百度收录
  • 企业网络架构拓扑图济南seo排名优化推广
  • 简易制作网站baidu百度
  • 建设企业网站企业网上银行登录官网百度小说搜索风云排行榜
  • 网站建设 域名 管理站长工具seo综合查询columbu cat
  • 贵阳 网站建设seo优化推广软件
  • 网站banner怎么设计seo网络推广技术