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()定义如下:
Ldate、Ltime等被定义为常量:
- func New(out io.Writer,prefix string,flag int) *Logger
- 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),它就是可以寻址的。