第4节 流程构建和分析
❤️💕💕Go语言高级篇章,在此之前建议您先了解基础和进阶篇。Myblog:http://nsddd.top
Go语言基础篇
Go语言100篇进阶
[TOC]
创建一个go-mod和仓库
PS C:\Users\smile\Desktop\log-monitoring> go mod init github.com/3293172751/log-monitoring/tree/master
go: creating new go.mod: module github.com/3293172751/log-monitoring/tree/master
程序框架
package main
type LogProcess struct {
rc chan string //多个goroutine之间的数据同步和通信(channels)
wc chan string //写入模块同步数据
//系统分为三个模块
// + 实时读取 -- 文件路径
// + 解析
// + 写入 -- 写入的时候需要ip
path string //读取文件的路径
influxDBsn string //写入的信息
}
func (l *LogProcess) ReadFromFile() {
//读取模块
}
func (l *LogProcess) Process() {
//解析模块
}
func (l *LogProcess) WriteToInfluxDB() {
//写入模块
}
func main() {
logprocess := &LogProcess{
rc: make(chan string),
wc: make(chan string),
path: "log/access.log",
influxDBsn: "username&password..",
}
//使用goroutinue提高程序的性能
go (*lp)logprocess.ReadFromFile() //调用读取模块
go logprocess.Process() //调用解析模块
go logprocess.WriteToInfluxDB() //调用写入模块
//程序执行完后就自动退出了
time.Sleep(1 * time.Second)
}
使用*LogProcess
引用类型原因:
func (l *LogProcess) Process() {
//解析模块
}
logprocess := &LogProcess{}
- 不用拷贝,对于性能有很大的提升
- 用引用就可以用
l
参数直接修改结构体的数值
程序测试
func (l *LogProcess) ReadFromFile() {
//读取模块
line := "message"
l.rc <- line //数据的流向
}
func (l *LogProcess) Process() {
//解析模块
data := <-l.rc
l.wc <- strings.ToUpper(data)
//处理数据--将data中的所有字符修改为其大写格式。对于非ASCII字符,它的大写格式需要查表转换
}
func (l *LogProcess) WriteToInfluxDB() {
//写入模块
fmt.Println(<-l.wc)
}
编译结果
[Running] go run "c:\Users\smile\Desktop\log-monitoring\log_process.go"
MESSAGE
程序优化
我们只能往WriteToInfluxDB()
中写入数据,如果有更多的数据(队列或者标准输出中),此时需要用到接口模式,把写入和读出模块抽象出来
用来约束实现类的功能。
package main
import (
"fmt"
"strings"
"time"
)
type Reader interface {
Read(rc chan string)
}
type Writer interface {
Writer(wc chan string)
}
type LogProcess struct {
rc chan string //多个goroutine之间的数据同步和通信(channels)
wc chan string //写入模块同步数据
//系统分为三个模块
// + 实时读取 -- 文件路径
// + 解析
// + 写入 -- 写入的时候需要
read Reader //接口定义
write Writer
}
type ReadFromFile struct {
path string //读取文件的路径
}
type WriteToInfluxDB struct {
influxDBsn string //写入的信息
}
func (r *ReadFromFile) Read(rc chan string) {
//读取模块
line := "messAge"
rc <- line //数据的流向
}
func (l *LogProcess) Process() {
//解析模块
data := <-l.rc
l.wc <- strings.ToUpper(data)
//处理数据--将data中的所有字符修改为其大写格式。对于非ASCII字符,它的大写格式需要查表转换
}
func (w *WriteToInfluxDB) Writer(wc chan string) {
//写入模块
fmt.Println(<-wc)
}
func main() {
r := &ReadFromFile{
path: "log/access.log",
}
w := &WriteToInfluxDB{
influxDBsn: "username&password..",
}
logprocess := &LogProcess{
rc: make(chan string),
wc: make(chan string),
read: r,
write: w,
}
//使用goroutinue提高程序的性能
go logprocess.read.Read(logprocess.rc) //调用读取模块
go logprocess.Process() //调用解析模块
go logprocess.write.Writer(logprocess.wc) //调用写入模块
//程序执行完后就自动退出了,需要等待
time.Sleep(1 * time.Second)
}
程序编译
[Running] go run "c:\Users\smile\Desktop\log-monitoring\log_process.go"
MESSAGE
为什么我们定义了两个接口就提升了它的可扩展性呢?
看起来程序虽然更加复杂了,但是我们如果后期添加新的读取写入模块,只需要对接口修改