工作中用go语言写了点脚本代替python的功能,涉及文件读写,记录如下
package main import ( "os" "os/exec" "log" "bytes" "strings" "bufio" //文件读写 "strconv" // "fmt" ) const pwd = "/usr/local/nginx/htdocs/" func get_logname(ziplog_name string) (string) { var out bytes.Buffer //hint:用exec.Command获取一个Cmd对象,设置标准输出到out,执行Run操作 cmd := exec.Command("unzip","-o",ziplog_name,"-d",ziplog_name[0:len(ziplog_name)-4]) cmd.Stdout = &out err := cmd.Run() if err != nil { log.Fatal(err) } //hint:标准输出可通过out.String()获取,用strings.Index获取指定字符串所在位置 i:=strings.Index(out.String(),"inflating: ") log_name:=out.String()[i+len("inflating: "):] //hint:通过strings.Trim删除字符串两侧的换行符以及空格 log_name = strings.Trim(log_name,"\n ") return log_name } func getinfo(line string)(string,string,string) { appname, day, curhour := "", "", "" //用strings的库函数拆分字符串,可以用&&添加多个判断 if info := strings.Split(line, " "); len(info) > 5 && info[3] == "OK" { appname = info[4] } if tday := strings.Split(line, "["); len(tday) > 1 { tday = strings.Split(tday[1]," ") day = ... } if hour := strings.Split(line, ":"); len(hour) > 1 { //hint 用strconv库函数判断字符串是否为数字 _, err := strconv.Atoi(hour[1]) if err != nil { return "","","" } curhour = hour[1] } return appname, day, curhour } func saveline(filepath, filename, line string) { //打开文件,如果失败,创建文件夹先,打开方式为append,和读写 f, err := os.OpenFile(filename, os.O_APPEND|os.O_RDWR, 0666) if err != nil { //如果文件夹已经创建,返回nil,MkdirAll是递归创建子目录 err = os.MkdirAll(filepath, 0755) if err != nil { log.Fatal(err) } f, err = os.OpenFile(filename, os.O_APPEND|os.O_RDWR, 0666) if err != nil { //如果文件不存在,则用Create创建,默认打开类型为读写 f, err = os.Create(filename) if err != nil { log.Fatal(err) } } } //设置defer关闭文件 defer f.Close() //hint:用bufio逐行写入文件 line = line + "\n" b := bufio.NewWriter(f) if n, err := b.WriteString(line); err != nil || n != len(line) { log.Fatal(err) } //hint:调用Flush将内存写到磁盘 if err = b.Flush(); err != nil { log.Fatal(err) } } func worker(line, p1, p2 string) { app, day, hour := getinfo(line) var filepath, filename string if day == "" || hour == "" { return } if app != "" { filepath = pwd + "workdir/app/" + app + "/" + day + "/" filename = filepath + hour + ".log" saveline(filepath, filename, line) } filepath = pwd + "workdir/backup/" + day + "/" + log_from + "/" filename = filepath + hour + ".log" saveline(filepath, filename, line) } func main() { //hint :os.Args获取命令行参数,用len获取参数个数 if len(os.Args) < 3 { log.Panic("fatal error") } para1, para2 := os.Args[1], os.Args[2] //hint :调用os的函数Chdir实现目录切换 if err := os.Chdir(pwd + "workdir/"); err != nil { log.Panic("fatal error") } //hint :设置defer,函数退出时调用os.RemoveAll,递归删除子目录以及文件 defer os.RemoveAll("dir") defer f.Close() //hint :用os.Open打开文件以及bufio逐行读取 f, err := os.Open("file.exist") if err != nil { log.Fatal(err) } r := bufio.NewReader(f) line, _, err := r.ReadLine() for err == nil { worker(string(line),para1,para2) line, _, err = r.ReadLine() } }
日志记录到文件的方法如下:
package main import "io" import "log" import "os" const logFileName = "test.log" func main() { logf, err := os.OpenFile(logFileName, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0640) if err != nil { log.Fatalln(err) } log.SetOutput(logf) mylogger := log.New(io.MultiWriter(logf,os.Stdout),"",-1) log.Println("goes to logf") mylogger.Println("goes to stdout and logf") }
日志文本如下
2013/06/04 07:59:06 goes to logf 2013/06/04 07:59:06.526852 test.go:17: goes to stdout and logf
不知道如何做性能对比,不过从运行结果来看,cpu占用比python低非常多