這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
1. golang的log模組
golang的log模組可以很方便的建立自己的日誌記錄,包括記錄檔路徑,日誌格式等都可以自己定義。先來看一個程式:
package mainimport ("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) *Logger
Ldate、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 mainimport ("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,"\r\n",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 mainimport "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中的文本會傳給recoverpanic("panic is run")fmt.Println("body 2")}
4. golang的base64加解密
package mainimport ("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() {// encodehello := "hello world"debyte := base64Encode([]byte(hello))// decodeenbyte, 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 mainimport ("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 mainimport ("fmt""reflect")type MyStruct struct {name string}func (this *MyStruct) GetName() string {return this.name}func main() {fmt.Println("--------------")var a MyStructb := 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的,所以也就不能使用FieldByNamefmt.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()) //falsefmt.Println(p.Elem().CanSet()) //truep.Elem().SetString("newName")fmt.Println(c)}
執行結果:
--------------<main.MyStruct Value><*main.MyStruct Value>--------------abc--------------falsetrue--------------falsetruenewName
a和b的ValueOf()返回的是不一樣的值,因為b是用new()建立的,是個指標。
當前面的CanSet是一個指標的時候(p)它是不可定址的,但是當是p.Elem()(實際上就是*p),它就是可以定址的。