1. golang的log模块
golang的log模块可以很方便的创建自己的日志记录,包括日志文件路径,日志格式等都可以自己定义。先来看一个程序:
package main import ( "fmt" "log" "os" ) func main() { logfile,err := os.OpenFile("d:\\test.log",os.O_RDWR|os.O_CREATE,0) if err != nil { fmt.Printf("%s\r\n",err.Error()) os.Exit(-1) } defer logfile.Close() logger := log.New(logfile,"\r\n",log.Ldate|log.Ltime|log.Llongfile) logger.Println("hello") logger.Println("oh....") logger.Fatal("test") logger.Fatal("test2") }
首先创建一个log文件,然后利用log.New()创建一个Logger对象,并定义log文件内容的格式,New()定义如下:
func New(out io.Writer,prefix string,flag int) *LoggerLdate、Ltime等被定义为常量:
const ( // Bits or'ed together to control what's printed. There is no control over the // order they appear (the order listed here) or the format they present (as // described in the comments). A colon appears after these items: // 2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message Ldate = 1 << iota // the date: 2009/01/23 Ltime // the time: 01:23:23 Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime. Llongfile // full file name and line number: /a/b/c/d.go:23 Lshortfile // final file name element and line number: d.go:23. overrides Llongfile LstdFlags = Ldate | Ltime // initial values for the standard logger )
通过Print()、Println()、Printf()等函数可以向log文件中写入log记录了。然后调用Fatal()等函数记录最后一条log,并退出(Fatal()中包含了调用os.Exit(1))。
Logger给出的结论是:A Logger can be used simultaneously from multiple goroutines; it guarantees to serialize access to the Writer. 也就是说是线程安全的。
2. golang的archive/zip模块
此模块比较简单,直接用一个程序说明:
package main import ( "fmt" "os" "log" "archive/zip" "io" ) const ( LOGFILEPATH = "d:\\zip.log" ) func main(){ logfile,err := os.OpenFile(LOGFILEPATH,os.O_CREATE|os.O_RDWR,0); if err!=nil { fmt.Println(err.Error()); return; } defer logfile.Close(); logger := log.New(logfile,log.Ldate|log.Ltime|log.Llongfile); if logger==nil { fmt.Println("logger init error"); } r,err := zip.OpenReader("d:\\新建文本文档.zip"); if err!=nil { logger.Fatal(err); } defer r.Close(); for _,f := range r.File { fmt.Println("FileName : ",f.Name); rc,err := f.Open(); if err!=nil { logger.Fatal(err); } _,err = io.CopyN(os.Stdout,rc,68); //打印文件内容 if err!=nil { if err!=io.EOF { logger.Fatal(err); } } } }
3. panic与recover
第一篇文章已经介绍过,这里再来一个例子:
package main import "fmt" func main() { T() //recover执行后,这里会继续执行 fmt.Println("after recover.") } func T() { defer func() { fmt.Println("defer func is run") //recover只能在defer()函数中执行 r := recover() if r != nil { fmt.Println("recover: ",r) } }() fmt.Println("body") //panic中的文本会传给recover panic("panic is run") fmt.Println("body 2") }
4. golang的base64加解密
package main import ( "encoding/base64" "fmt" ) const ( base64Table = "123QRSTUabcdVWXYZHijKLAWDCABDstEFGuvwxyzGHIJklmnopqr234560178912" ) var coder = base64.NewEncoding(base64Table) func base64Encode(src []byte) []byte { return []byte(coder.EncodeToString(src)) } func base64Decode(src []byte) ([]byte,error) { return coder.DecodeString(string(src)) } func main() { // encode hello := "hello world" debyte := base64Encode([]byte(hello)) // decode enbyte,err := base64Decode(debyte) if err != nil { fmt.Println(err.Error()) } if hello != string(enbyte) { fmt.Println("hello is not equal to enbyte") } fmt.Println(string(enbyte)) }
5. golang的time包
package main import ( "fmt" "time" ) func main() { //时间戳 t := time.Now().Unix() fmt.Println(t) //时间戳到具体显示的转化 fmt.Println(time.Unix(t,0).String()) //带纳秒的时间戳 t = time.Now().UnixNano() fmt.Println(t) fmt.Println("------------------") //基本格式化的时间表示 fmt.Println(time.Now().String()) fmt.Println(time.Now().Format("2006year 01month 02day")) }输出今天是星期几:
package main import ( "fmt" "time" ) func main() { //时间戳 t := time.Now() fmt.Println(t.Weekday().String()) }
6. golang反射举例
package main import ( "fmt" "reflect" ) type MyStruct struct { name string } func (this *MyStruct) GetName() string { return this.name } func main() { fmt.Println("--------------") var a MyStruct b := new(MyStruct) fmt.Println(reflect.ValueOf(a)) fmt.Println(reflect.ValueOf(b)) fmt.Println("--------------") a.name = "abc" b.name = "def" val := reflect.ValueOf(a).FieldByName("name") fmt.Println(val) //val2 := reflect.ValueOf(b).FieldByName("name") //panic: reflect: call of reflect.Value.FieldByName on ptr Value //b是一个指针,指针的ValueOf返回的是指针的Type,它是没有Field的,所以也就不能使用FieldByName fmt.Println("--------------") fmt.Println(reflect.ValueOf(a).FieldByName("name").CanSet()) fmt.Println(reflect.ValueOf(&(a.name)).Elem().CanSet()) fmt.Println("--------------") var c string = "xyz" p := reflect.ValueOf(&c) fmt.Println(p.CanSet()) //false fmt.Println(p.Elem().CanSet()) //true p.Elem().SetString("newName") fmt.Println(c) }
执行结果:
-------------- <main.MyStruct Value> <*main.MyStruct Value> -------------- abc -------------- false true -------------- false true newName
a和b的ValueOf()返回的是不一样的值,因为b是用new()创建的,是个指针。
当前面的CanSet是一个指针的时候(p)它是不可寻址的,但是当是p.Elem()(实际上就是*p),它就是可以寻址的。