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) *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 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,"\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 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),它就是可以寻址的。