网站按钮确定后图片怎么做,域名怎么做网站内容,网页设计需求分析范文,在线制作头像文字图片文章目录 本文目标新建logging包file.go编写log文件当前目录结构 接入自定义的log功能验证功能 _ 学习煎鱼大佬的该项目 煎鱼大佬网站 原github地址 个人github项目地址#xff0c;希望得到一点star
本文目标
在上一节中#xff0c;我们解决了 API’s 可以任意访问的问题logging包file.go编写log文件当前目录结构 接入自定义的log功能验证功能 _ 学习煎鱼大佬的该项目 煎鱼大佬网站 原github地址 个人github项目地址希望得到一点star
本文目标
在上一节中我们解决了 API’s 可以任意访问的问题那么我们现在还有一个问题就是我们的日志都是输出到控制台上的这显然对于一个项目来说是不合理的因此我们这一节简单封装log库使其支持简单的文件日志
新建logging包
我们在pkg下新建logging目录用来包含自定义logger相关的文件,新建file.go和log.go文件
file.go
用来创建记录log的相关目录和文件其内容为
package loggingimport (fmtlogostime
)// 适用枚举将所有固定的量提前列出在这里方便后期维护 我们这里将原来的var修改为const
const (LogSavePath runtime/logs/LogSaveName logLogFileExt logTimeFormat 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返回文件信息结构描述文件。如果出现错误会返回*PathErrortype PathError struct {Op stringPath stringErr error
}os.IsNotExist能够接受ErrNotExist、syscall的一些错误它会返回一个布尔值能够得知文件不存在或目录不存在os.IsPermission能够接受ErrPermission、syscall的一些错误它会返回一个布尔值能够得知权限是否满足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 ored 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否则返回erroros.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 (fmtlogospath/filepathruntime
)// 类型声明基于int建立level方便后续维护
type Level intvar (//传入写log文件的句柄F *os.File//默认的前缀DefaultPrefix //这里的定义在后续的caller中被调用该参数指定了要跳过的调用堆栈帧数每个调用堆栈帧代表了代码中的一个函数调用。//以info写入log为例我们这里调用caller的函数为setPrefixInfo调用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包的代码如下
打开routers目录下的article.go、tag.go、auth.go。 2。 将log包的引用删除修改引用我们自己的日志包为github.com/kingsill/gin-example/pkg/logging。将原本的log.Println(...)改为logging.Info(...)。
验证功能
修改文件后重启服务我们来试试吧
获取到 API 的 Token 后我们故意传错误 URL 参数给接口如http://127.0.0.1:8000/api/v1/articles?tag_id0state9999999tokeneyJhbG..
然后我们到$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因此前缀是对的并且我们是入参有问题也把错误记录下来了这样排错就很方便了
至此本节就完成了这只是一个简单的扩展实际上我们线上项目要使用的文件日志是更复杂一些开动你的大脑 举一反三吧