Go語言中log模塊用於在程序中輸出日誌。
log模塊提供了三類日誌輸出接口,Print、Fatal和Panic。Print是普通輸出;Fatal是在執行完Print後,執行 os.Exit(1);Panic是在執行完Print後調用panic()方法。log模塊對每一類接口其提供了3中調用方式,分別是"Xxxx、 Xxxxln、Xxxxf"。正則表達式
log.Print類接口包括log.Print、log.Println、log.Printf,接口以下:app
// Printf calls l.Output to print to the logger. // Arguments are handled in the manner of fmt.Printf. func (l *Logger) Printf(format string, v ...interface{}) { l.Output(2, fmt.Sprintf(format, v...)) } // Print calls l.Output to print to the logger. // Arguments are handled in the manner of fmt.Print. func (l *Logger) Print(v ...interface{}) { l.Output(2, fmt.Sprint(v...)) } // Println calls l.Output to print to the logger. // Arguments are handled in the manner of fmt.Println. func (l *Logger) Println(v ...interface{}) { l.Output(2, fmt.Sprintln(v...)) }
log.Print類接口使用示例:ide
package main import ( "log" ) func logPrintTest(){ arr := []int {2,3} log.Print("Print array ",arr,"\n") log.Println("Println array",arr) log.Printf("Printf array with item [%d,%d]\n",arr[0],arr[1]) } func main() { logPrintTest() } // output // 2018/10/06 13:38:29 Print array [2 3] // 2018/10/06 13:38:29 Println array [2 3] // 2018/10/06 13:38:29 Printf array with item [2,3]
log.Fatal類接口包括log.Fatal、log.Fatalln、log.Fatalf,接口以下:函數
// Fatal is equivalent to l.Print() followed by a call to os.Exit(1). func (l *Logger) Fatal(v ...interface{}) { l.Output(2, fmt.Sprint(v...)) os.Exit(1) } // Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1). func (l *Logger) Fatalf(format string, v ...interface{}) { l.Output(2, fmt.Sprintf(format, v...)) os.Exit(1) } // Fatalln is equivalent to l.Println() followed by a call to os.Exit(1). func (l *Logger) Fatalln(v ...interface{}) { l.Output(2, fmt.Sprintln(v...)) os.Exit(1) }
log.Fata接口會先將日誌內容打印到標準輸出,接着調用系統的 os.exit(1)接口,退出程序並返回狀態1 。但因爲直接調用系統接口退出,defer函數不會被調用。
log.Fatal接口使用示例:oop
package main import ( "log" "fmt" ) func logFatalTest(){ level := "Fatal" defer func() { fmt.Println("defer Fatal") }() log.Fatal("print ",level, " level\n") // 後續不會被執行 log.Fatalln("print ",level) log.Fatalf("print %s level", level) } func main() { logFatalTest() } // output // 2018/10/06 13:47:57 print Fatal level
log.Fatal接口調用會致使程序退出。ui
log.Panic類接口包括log.Panic、log.Panicln、log.Panicf,接口以下:debug
// Panic is equivalent to l.Print() followed by a call to panic(). func (l *Logger) Panic(v ...interface{}) { s := fmt.Sprint(v...) l.Output(2, s) panic(s) } // Panicf is equivalent to l.Printf() followed by a call to panic(). func (l *Logger) Panicf(format string, v ...interface{}) { s := fmt.Sprintf(format, v...) l.Output(2, s) panic(s) } // Panicln is equivalent to l.Println() followed by a call to panic(). func (l *Logger) Panicln(v ...interface{}) { s := fmt.Sprintln(v...) l.Output(2, s) panic(s) }
log.Panic接口函數把日誌內容刷到標準錯誤後調用panic函數。
log.Panic接口使用示例:日誌
package main import ( "log" "fmt" ) func logPanicTest(){ level := "Panic" defer func() { fmt.Println("defer Panic 1") if err := recover(); err != nil { fmt.Println(err) } }() log.Panic(level, " level") defer func() { fmt.Println("defer Panic 2") }() } func main() { logPanicTest() } // output // defer Panic 1 // 2018/10/06 13:55:17 Panic level // Panic level
第一個defer函數被調用並輸出「defer Panic 1」,Panic後聲明的defer不會執行。code
Logger是寫入日誌的基本組件,log模塊中存在一個標準Logger,能夠直接經過log進行訪問,能夠直接使用log.xxxx進行日誌進行輸出。但在實際使用中,不一樣類型的日誌可能擁有需求,僅標準Logger不能知足日誌記錄的需求,經過建立不一樣的Logger能夠將不一樣類型的日誌分類輸出。使用logger前須要首先經過New函數建立一個Logger對象,函數聲明以下:regexp
func New(out io.Writer, prefix string, flag int) *Logger { return &Logger{out: out, prefix: prefix, flag: flag} }
函數接收三個參數分別是日誌輸出的IO對象,日誌前綴和日誌包含的通用信息標識位,經過對參數進行設置能夠對Logger進行定製。其中IO對象一般是標準輸出os.Stdout,os.Stderr,或者綁定到文件的IO。日誌前綴和信息標識位能夠對日誌的格式進行設置。
一條日誌由三個部分組成,其結構以下:{日誌前綴} {標識1} {標識2} ... {標識n} {日誌內容}
日誌前綴,經過prefix參數設置,能夠是任意字符串。
標識,經過flags參數設置,當某個標識被設置,會在日誌中進行顯示,log模塊中定義了以下標識,多個標識經過按位或進行組合:
Ldate 顯示當前日期(當前時區)
Ltime 顯示當前時間(當前時區)
Lmicroseconds 顯示當前時間(微秒)
Llongfile 包含路徑的完整文件名
Lshortfile 不包含路徑的文件名
LUTC Ldata和Ltime使用UTC時間
LstdFlags 標準Logger的標識,等價於 Ldate | Ltime
Logger相關接口以下:
// Flags returns the output flags for the logger. func (l *Logger) Flags() int { l.mu.Lock() defer l.mu.Unlock() return l.flag } // SetFlags sets the output flags for the logger. func (l *Logger) SetFlags(flag int) { l.mu.Lock() defer l.mu.Unlock() l.flag = flag } // Prefix returns the output prefix for the logger. func (l *Logger) Prefix() string { l.mu.Lock() defer l.mu.Unlock() return l.prefix } // SetPrefix sets the output prefix for the logger. func (l *Logger) SetPrefix(prefix string) { l.mu.Lock() defer l.mu.Unlock() l.prefix = prefix } // SetOutput sets the output destination for the standard logger. func SetOutput(w io.Writer) { std.mu.Lock() defer std.mu.Unlock() std.out = w } // Flags returns the output flags for the standard logger. func Flags() int { return std.Flags() } // SetFlags sets the output flags for the standard logger. func SetFlags(flag int) { std.SetFlags(flag) } // Prefix returns the output prefix for the standard logger. func Prefix() string { return std.Prefix() } // SetPrefix sets the output prefix for the standard logger. func SetPrefix(prefix string) { std.SetPrefix(prefix) }
Logger示例以下:
package main import ( "log" "os" ) func main() { prefix := "[INFO]" logger := log.New(os.Stdout, prefix, log.LstdFlags | log.Lshortfile) logger.Print("Hello Go") logger.SetPrefix("[OUTPUT]") logger.SetFlags(log.LstdFlags) logger.Print("Hello Logger") } // output // [INFO]2018/10/06 13:24:44 main.go:11: Hello Go // [OUTPUT]2018/10/06 13:24:44 Hello Logger
Go的log模塊沒有對日誌進行分級的功能,對於日誌分級需求能夠在log的基礎上進行實現。經過使用log模塊的基礎功能進行封裝,能夠實現Log4相似的日誌功能。
package logger import ( "fmt" "log" "os" "os/exec" "strings" "time" ) const ( PanicLevel int = iota FatalLevel ErrorLevel WarnLevel InfoLevel DebugLevel ) type LogFile struct { level int logTime int64 fileName string fileFd *os.File } var logFile LogFile func Config(logFolder string, level int) { logFile.fileName = logFolder logFile.level = level log.SetOutput(logFile) log.SetFlags(log.Lmicroseconds | log.Lshortfile) } func SetLevel(level int) { logFile.level = level } func Debugf(format string, args ...interface{}) { if logFile.level >= DebugLevel { log.SetPrefix("debug ") log.Output(2, fmt.Sprintf(format, args...)) } } func Infof(format string, args ...interface{}) { if logFile.level >= InfoLevel { log.SetPrefix("info ") log.Output(2, fmt.Sprintf(format, args...)) } } func Warnf(format string, args ...interface{}) { if logFile.level >= WarnLevel { log.SetPrefix("warn ") log.Output(2, fmt.Sprintf(format, args...)) } } func Errorf(format string, args ...interface{}) { if logFile.level >= ErrorLevel { log.SetPrefix("error ") log.Output(2, fmt.Sprintf(format, args...)) } } func Fatalf(format string, args ...interface{}) { if logFile.level >= FatalLevel { log.SetPrefix("fatal ") log.Output(2, fmt.Sprintf(format, args...)) } } func (me LogFile) Write(buf []byte) (n int, err error) { if me.fileName == "" { fmt.Printf("consol: %s", buf) return len(buf), nil } if logFile.logTime+3600 < time.Now().Unix() { logFile.createLogFile() logFile.logTime = time.Now().Unix() } if logFile.fileFd == nil { return len(buf), nil } return logFile.fileFd.Write(buf) } func (me *LogFile) createLogFile() { logdir := "./" if index := strings.LastIndex(me.fileName, "/"); index != -1 { logdir = me.fileName[0:index] + "/" os.MkdirAll(me.fileName[0:index], os.ModePerm) } now := time.Now() filename := fmt.Sprintf("%s_%04d%02d%02d_%02d%02d", me.fileName, now.Year(), now.Month(), now.Day(), now.Hour(), now.Minute()) if err := os.Rename(me.fileName, filename); err == nil { go func() { tarCmd := exec.Command("tar", "-zcf", filename+".tar.gz", filename, "--remove-files") tarCmd.Run() rmCmd := exec.Command("/bin/sh", "-c", "find "+logdir+` -type f -mtime +2 -exec rm {} \;`) rmCmd.Run() }() } for index := 0; index < 10; index++ { if fd, err := os.OpenFile(me.fileName, os.O_CREATE|os.O_APPEND|os.O_WRONLY, os.ModeExclusive); nil == err { me.fileFd.Sync() me.fileFd.Close() me.fileFd = fd break } me.fileFd = nil } }
上述logger模塊封裝的功能以下:
A、支持歸檔輸出,一個小時壓縮歸檔一份
B、最多保留三天的日誌
C、支持日誌級別自定義
D、若是沒有指定輸出文件默認輸出到控制檯。
E、支持輸出文件名行號,以及時間、日誌界別
Go語言經過regexp標準包爲正則表達式提供了官方支持。在Go語言環境中可使用下列命令查看正則表達式的語法:go doc regexp/syntax
Regexp是一個編譯好的正則表達式對象。
type Regexp struct { // read-only after Compile regexpRO // cache of machines for running regexp mu sync.Mutex machine []*machine }
一般須要使用正則表達式構建一個正則對象
func Match(pattern string, b []byte) (matched bool, err error) func MatchString(pattern string, s string) (matched bool, err error) func MatchReader(pattern string, r io.RuneReader) (matched bool, err error)
判斷在b中可否找到pattern所匹配的字符串func Compile(expr string) (*Regexp, error)
將正則表達式編譯成一個正則對象(使用PERL語法)。
該正則對象會採用「leftmost-first」模式。選擇第一個匹配結果。
若是正則表達式語法錯誤,則返回錯誤信息。func CompilePOSIX(expr string) (*Regexp, error)
將正則表達式編譯成一個正則對象(正則語法限制在 POSIX ERE 範圍內)。
該正則對象會採用「leftmost-longest」模式。選擇最長的匹配結果。
POSIX 語法不支持Perl的語法格式:\d、\D、\s、\S、\w、\W
若是正則表達式語法錯誤,則返回錯誤信息。
func MustCompile(str string) *Regexp func MustCompilePOSIX(str string) *Regexp
將正則表達式編譯成一個正則對象,但會在解析失敗時panicfunc (re *Regexp) Longest()
讓正則表達式在以後的搜索中都採用「leftmost-longest」模式。func (re *Regexp) String() string
返回編譯時使用的正則表達式字符串func (re *Regexp) NumSubexp() int
返回正則表達式中分組的數量func (re *Regexp) SubexpNames() []string
返回正則表達式中分組的名字
第 0 個元素表示整個正則表達式的名字,永遠是空字符串。func (re *Regexp) LiteralPrefix() (prefix string, complete bool)
返回正則表達式必須匹配到的字面前綴(不包含可變部分)。
若是整個正則表達式都是字面值,則 complete 返回 true。
package main import ( "regexp" "fmt" ) var mailRegexp = regexp.MustCompile(`([A-Za-z0-9]+)@([A-Za-z0-9.]+)\.([A-Za-z0-9.]+)`) func main() { s := " hello's email is hellogo@gmail.com" matches := mailRegexp.FindStringSubmatch(s) fmt.Println(matches)// [hellogo@gmail.com hellogo gmail com] fmt.Println(matches[0]) // hellogo@gmail.com fmt.Println(matches[1]) // hellogo fmt.Println(matches[2]) // gmail fmt.Println(matches[3]) // com }
strconv提供了字符串與基本類型的轉換函數接口。
func ParseBool(str string) (value bool, err error)
ParseBool將字符串轉換爲布爾值。接受真值:1, t, T, TRUE, true, True;接受假值:0, f, F, FALSE, false, False;其它任何值都返回一個錯誤。
package main import ( "fmt" "strconv" ) func main() { fmt.Println(strconv.ParseBool("1")) // true fmt.Println(strconv.ParseBool("t")) // true fmt.Println(strconv.ParseBool("T")) // true fmt.Println(strconv.ParseBool("true")) // true fmt.Println(strconv.ParseBool("True")) // true fmt.Println(strconv.ParseBool("TRUE")) // true fmt.Println(strconv.ParseBool("TRue")) // false strconv.ParseBool: parsing "TRue": invalid syntax fmt.Println(strconv.ParseBool("0")) // false fmt.Println(strconv.ParseBool("f")) // false fmt.Println(strconv.ParseBool("F")) // false fmt.Println(strconv.ParseBool("false")) // false fmt.Println(strconv.ParseBool("False")) // false fmt.Println(strconv.ParseBool("FALSE")) // false fmt.Println(strconv.ParseBool("FALse")) // false strconv.ParseBool: parsing "FAlse": invalid syntax }
func FormatBool(b bool) string
FormatBool將布爾值轉換爲字符串"true"或"false"
package main import ( "fmt" "strconv" ) func main() { fmt.Println(strconv.FormatBool(0 < 1)) // true fmt.Println(strconv.FormatBool(0 > 1)) // false }
func AppendBool(dst []byte, b bool) []byte
AppendBool將布爾值b轉換爲字符串"true"或"false",而後將結果追加到dst的尾部,返回追加後的[]byte。
package main import ( "fmt" "strconv" ) func main() { rst := make([]byte, 0) rst = strconv.AppendBool(rst, 0 < 1) fmt.Printf("%s\n", rst) // true rst = strconv.AppendBool(rst, 0 > 1) fmt.Printf("%s\n", rst) // truefalse }
func ParseInt(s string, base int, bitSize int) (i int64, err error)
ParseInt將字符串轉換爲int類型
s:要轉換的字符串
base:進位制(2進制到36進制)
bitSize:指定整數類型(0:int、8:int八、16:int1六、32:int3二、64:int64)
返回轉換後的結果和轉換時遇到的錯誤,若是base爲0,則根據字符串的前綴判斷進位制(0x:16,0:8,其它:10)。
package main import ( "fmt" "strconv" ) func main() { fmt.Println(strconv.ParseInt("123", 10, 8)) // 123 fmt.Println(strconv.ParseInt("12345", 10, 8)) // 127 strconv.ParseInt: parsing "12345": value out of range fmt.Println(strconv.ParseInt("2147483647", 10, 0)) // 2147483647 fmt.Println(strconv.ParseInt("0xFF", 16, 0)) // 0 strconv.ParseInt: parsing "0xFF": invalid syntax fmt.Println(strconv.ParseInt("FF", 16, 0)) // 255 fmt.Println(strconv.ParseInt("0xFF", 0, 0)) // 255 }
func ParseUint(s string, base int, bitSize int) (n uint64, err error)
ParseUint將字符串轉換爲uint類型
package main import ( "fmt" "strconv" ) func main() { fmt.Println(strconv.ParseUint("FF", 16, 8)) // 255 }
func Atoi(s string) (i int, err error)
Atoi至關於ParseInt(s, 10, 0)
func FormatInt(i int64, base int) string
FormatUint將int型整數i轉換爲字符串形式
base:進位制(2進制到36進制),大於10進制的數,返回值使用小寫字母'a'到'z'
package main import ( "fmt" "strconv" ) func main() { i := int64(-2048) fmt.Println(strconv.FormatInt(i, 2)) // -100000000000 fmt.Println(strconv.FormatInt(i, 8)) // -4000 fmt.Println(strconv.FormatInt(i, 10)) // -2048 fmt.Println(strconv.FormatInt(i, 16)) // -800 fmt.Println(strconv.FormatInt(i, 36)) // -1kw }
func Itoa(i int) string
Itoa至關於FormatInt(i, 10)
func AppendInt(dst []byte, i int64, base int) []byte
AppendInt將int型整數i轉換爲字符串形式,並追加到dst的尾部
i:要轉換的字符串,base:進位制,返回追加後的[]byte。
func AppendUint(dst []byte, i uint64, base int) []byte
AppendUint將uint型整數i轉換爲字符串形式,並追加到dst的尾部
i:要轉換的字符串,base:進位制,返回追加後的[]byte。
func ParseFloat(s string, bitSize int) (f float64, err error)
ParseFloat將字符串轉換爲浮點數,
s:要轉換的字符串
bitSize:指定浮點類型(32:float3二、64:float64)
若是s是合法的格式,並且接近一個浮點值,則返回浮點數的四捨五入值(依據 IEEE754 的四捨五入標準);若是s不是合法的格式,則返回「語法錯誤」;若是轉換結果超出bitSize範圍,則返回「超出範圍」。
package main import ( "fmt" "strconv" ) func main() { s := "0.12345678901234567890" f, err := strconv.ParseFloat(s, 32) fmt.Println(f, err) // 0.12345679104328156 fmt.Println(float32(f), err) // 0.12345679 f, err = strconv.ParseFloat(s, 64) fmt.Println(f, err) // 0.12345678901234568 }
func FormatFloat(f float64, fmt byte, prec, bitSize int) string
FormatFloat 將浮點數 f 轉換爲字符串值
f:要轉換的浮點數
fmt:格式標記(b、e、E、f、g、G)
prec:精度(數字部分的長度,不包括指數部分)
bitSize:指定浮點類型(32:float3二、64:float64)
格式標記:
'b' (-ddddp±ddd,二進制指數)
'e' (-d.dddde±dd,十進制指數)
'E' (-d.ddddE±dd,十進制指數)
'f' (-ddd.dddd,沒有指數)
'g' ('e':大指數,'f':其它狀況)
'G' ('E':大指數,'f':其它狀況)
若是格式標記爲 'e','E'和'f',則prec表示小數點後的數字位數
若是格式標記爲 'g','G',則prec表示總的數字位數(整數部分+小數部分)
package main import ( "fmt" "strconv" ) func main() { f := 100.12345678901234567890123456789 fmt.Println(strconv.FormatFloat(f, 'b', 5, 32)) // 13123382p-17 fmt.Println(strconv.FormatFloat(f, 'e', 5, 32)) // 1.00123e+02 fmt.Println(strconv.FormatFloat(f, 'E', 5, 32)) // 1.00123E+02 fmt.Println(strconv.FormatFloat(f, 'f', 5, 32)) // 100.12346 fmt.Println(strconv.FormatFloat(f, 'g', 5, 32)) // 100.12 fmt.Println(strconv.FormatFloat(f, 'G', 5, 32)) // 100.12 fmt.Println(strconv.FormatFloat(f, 'b', 30, 32)) // 13123382p-17 fmt.Println(strconv.FormatFloat(f, 'e', 30, 32)) // 1.001234588623046875000000000000e+02 fmt.Println(strconv.FormatFloat(f, 'E', 30, 32)) // 1.001234588623046875000000000000E+02 fmt.Println(strconv.FormatFloat(f, 'f', 30, 32)) // 100.123458862304687500000000000000 fmt.Println(strconv.FormatFloat(f, 'g', 30, 32)) // 100.1234588623046875 fmt.Println(strconv.FormatFloat(f, 'G', 30, 32)) // 100.1234588623046875 }
func AppendFloat(dst []byte, f float64, fmt byte, prec int, bitSize int) []byte
AppendFloat將浮點數f轉換爲字符串值,並將轉換結果追加到dst的尾部,返回追加後的[]byte
package main import ( "fmt" "strconv" ) func main() { f := 100.12345678901234567890123456789 b := make([]byte, 0) b = strconv.AppendFloat(b, f, 'f', 5, 32) b = append(b, " "...) b = strconv.AppendFloat(b, f, 'e', 5, 32) fmt.Printf("%s", b) // 100.12346 1.00123e+0 }
func Quote(s string) string
Quote將字符串s轉換爲「雙引號」引發來的字符串
其中的特殊字符將被轉換爲「轉義字符」,「不可顯示的字符」將被轉換爲「轉義字符」。
package main import ( "fmt" "strconv" ) func main() { fmt.Println(strconv.Quote(`/home/user`)) // "/home/user" }
func AppendQuote(dst []byte, s string) []byte
AppendQuote將字符串s轉換爲「雙引號」引發來的字符串,並將結果追加到dst的尾部,返回追加後的[]byte。其中的特殊字符將被轉換爲「轉義字符」。
func QuoteToASCII(s string) string
QuoteToASCII將字符串s轉換爲「雙引號」引發來的ASCII字符串,「非ASCII字符」和「特殊字符」將被轉換爲「轉義字符」。
func AppendQuoteToASCII(dst []byte, s string) []byte
AppendQuoteToASCII將字符串s轉換爲「雙引號」引發來的 ASCII 字符串,並將結果追加到dst的尾部,返回追加後的[]byte,「非 ASCII 字符」和「特殊字符」將被轉換爲「轉義字符」。
func QuoteRune(r rune) string
QuoteRune將Unicode字符轉換爲「單引號」引發來的字符串,「特殊字符」將被轉換爲「轉義字符」。
func AppendQuoteRune(dst []byte, r rune) []byte
AppendQuoteRune將Unicode字符轉換爲「單引號」引發來的字符串,並將結果追加到dst的尾部,返回追加後的[]byte。「特殊字符」將被轉換爲「轉義字符」。
func QuoteRuneToASCII(r rune) string
QuoteRuneToASCII將Unicode字符轉換爲「單引號」引發來的ASCII字符串,「非 ASCII字符」和「特殊字符」將被轉換爲「轉義字符」。
func AppendQuoteRuneToASCII(dst []byte, r rune) []byte
AppendQuoteRune將Unicode字符轉換爲「單引號」引發來的ASCII字符串,並將結果追加到dst的尾部,返回追加後的[]byte,「非 ASCII 字符」和「特殊字符」將被轉換爲「轉義字符」。
func CanBackquote(s string) bool
CanBackquote判斷字符串s是否能夠表示爲一個單行的「反引號」字符串,字符串中不能含有控制字符(除了\t)和「反引號」字符,不然返回false。
func UnquoteChar(s string, quote byte) (value rune, multibyte bool, tail string, err error)
UnquoteChar 將 s 中的第一個字符「取消轉義」並解碼
s:轉義後的字符串
quote:字符串使用的「引號符」(用於對引號符「取消轉義」)
value: 解碼後的字符
multibyte:value是否爲多字節字符
tail: 字符串s除去value後的剩餘部分
error:返回s中是否存在語法錯誤
參數 quote 爲「引號符」
若是設置爲單引號,則 s 中容許出現 \' 字符,不容許出現單獨的 ' 字符
若是設置爲雙引號,則 s 中容許出現 \" 字符,不容許出現單獨的 " 字符
若是設置爲 0,則不容許出現 \' 或 \" 字符,能夠出現單獨的 ' 或 " 字符
func Unquote(s string) (t string, err error)
Unquote 將「帶引號的字符串」 s 轉換爲常規的字符串(不帶引號和轉義字符)
s能夠是「單引號」、「雙引號」或「反引號」引發來的字符串(包括引號自己)
若是s是單引號引發來的字符串,則返回該該字符串表明的字符
func IsPrint(r rune) bool
IsPrint判斷Unicode字符r是不是一個可顯示的字符,空格能夠顯示,而\t則不能顯示。
time包提供顯示和計算時間用的函數。Go中時間處理依賴的數據類型: time.Time, time.Month, time.Weekday, time.Duration, time.Location。
time.Time 表明一個納秒精度的時間點,定義以下:
type Time struct { sec int64 // 從1年1月1日 00:00:00 UTC 至今過去的秒數 nsec int32 // 最近一秒到下一秒過去的納秒數 loc *Location // 時區 }
time.Time使用示例:
package main import ( "fmt" "time" ) func main() { var t time.Time // 定義 time.Time 類型變量 t = time.Now() // 獲取當前時間 fmt.Printf("時間: %v, 時區: %v, 時間類型: %T\n", t, t.Location(), t) // time.UTC() time 返回UTC 時區的時間 fmt.Printf("時間: %v, 時區: %v, 時間類型: %T\n", t.UTC(), t.UTC().Location(), t) } // output // 時間: 2018-10-06 15:31:06.730640277 +0800 CST m=+0.000273307, 時區: Local, 時間類型: time.Time // 時間: 2018-10-06 07:31:06.730640277 +0000 UTC, 時區: UTC, 時間類型: time.Time
時間獲取的接口:
func Now() Time {} // 當前本地時間 func Unix(sec int64, nsec int64) Time {} // 根據時間戳返回本地時間 func Date(year int, month Month, day, hour, min, sec, nsec int, loc *Location) Time {} // 返回指定時間 時間顯示的接口: func (t Time) UTC() Time {} // 獲取指定時間在UTC 時區的時間表示 func (t Time) Local() Time {} // 以本地時區表示 func (t Time) In(loc *Location) Time {} // 時間在指定時區的表示 func (t Time) Format(layout string) string {} // 按指定格式顯示時間
日期信息獲取的接口:
func (t Time) Date() (year int, month Month, day int) {} // 返回時間的日期信息 func (t Time) Year() int {} // 返回年 func (t Time) Month() Month {} // 月 func (t Time) Day() int {} // 日 func (t Time) Weekday() Weekday {} // 星期 func (t Time) ISOWeek() (year, week int) {} // 返回年,星期範圍編號 func (t Time) Clock() (hour, min, sec int) {} // 返回時間的時分秒 func (t Time) Hour() int {} // 返回小時 func (t Time) Minute() int {} // 分鐘 func (t Time) Second() int {} // 秒 func (t Time) Nanosecond() int {} // 納秒 func (t Time) YearDay() int {} // 一年中對應的天 func (t Time) Location() *Location {} // 時間的時區 func (t Time) Zone() (name string, offset int) {} // 時間所在時區的規範名和想對UTC 時間偏移量 func (t Time) Unix() int64 {} // 時間轉爲時間戳 func (t Time) UnixNano() int64 {} // 時間轉爲時間戳(納秒)
時間比較與計算的接口:
func (t Time) IsZero() bool {} // 是不是零時時間 func (t Time) After(u Time) bool {} // 時間在u 以前 func (t Time) Before(u Time) bool {} // 時間在u 以後 func (t Time) Equal(u Time) bool {} // 時間與u 相同 func (t Time) Add(d Duration) Time {} // 返回t +d 的時間點 func (t Time) Sub(u Time) Duration {} // 返回 t-u func (t Time) AddDate(years int, months int, days int) Time {} //返回增長了給出的年份、月份和天數的時間點Time
時間序列化的接口:
func (t Time) MarshalBinary() ([]byte, error) {} // 時間序列化 func (t Time) UnmarshalBinary(data []byte) error {} // 反序列化 func (t Time) MarshalJSON() ([]byte, error) {} // 時間序列化 func (t Time) MarshalText() ([]byte, error) {} // 時間序列化 func (t Time) GobEncode() ([]byte, error) {} // 時間序列化 func (t Time) GobDecode() ([]byte, error) {} // 時間序列化
time.Month 表明一年中的某個月
type Month int const ( January Month = 1 + iota February March April May June July August September October November December )
time.Weekday 表明一週的周幾
type Weekday int const ( Sunday Weekday = iota Monday Tuesday Wednesday Thursday Friday Saturday )
time.Duration 類型表明兩個時間點之間通過的納秒數,可表示的最長時間段約爲290年。
type Duration int64 const ( Nanosecond Duration = 1 Microsecond = 1000 * Nanosecond Millisecond = 1000 * Microsecond Second = 1000 * Millisecond Minute = 60 * Second Hour = 60 * Minute )
輸出和改變時間段單位的接口:
func (d Duration) String() string // 格式化輸出 Duration func (d Duration) Nanoseconds() int64 // 將時間段表示爲納秒 func (d Duration) Seconds() float64 // 將時間段表示爲秒 func (d Duration) Minutes() float64 // 將時間段表示爲分鐘 func (d Duration) Hours() float64 // 將時間段表示爲小時
Location表明一個地點,以及該地點所在的時區信息。北京時間可使用 Asia/Shanghai。
type Location struct { name string zone []zone tx []zoneTrans cacheStart int64 cacheEnd int64 cacheZone *zone } var UTC *Location = &utcLoc var Local *Location = &localLoc
時區導出的接口:
func (l *Location) String() string // 輸出時區名 func FixedZone(name string, offset int) *Location // FixedZone 使用給定的地點名name和時間偏移量offset(單位秒)建立並返回一個Location func LoadLocation(name string) (*Location, error) // LoadLocation 使用給定的名字建立Location
func Sleep(d Duration)
阻塞當前go協程至少d表明的時間段。d<=0時,Sleep會馬上返回。
Go語言使用error類型來返回函數執行過程當中遇到的錯誤,若是返回error值爲nil,則表示未遇到錯誤,不然error會返回一個字符串。error是一個預約義標識符,表明一個Go語言內建的接口類型,任何自定義的錯誤類型都要實現Error接口函數。
type error interface { Error() string }
func New(text string) error
將字符串text包裝成一個error對象返回
import ( "errors" "fmt" ) var ErrUnexpectedEOF = errors.New("unexpected EOF") func main() { fmt.Println(ErrUnexpectedEOF) }
Go語言工程開發中,一般須要根據使用場景定製不一樣的error類型,此時須要實現Error接口。
package errors_test import ( "fmt" "time" ) // MyError is an error implementation that includes a time and message. type MyError struct { When time.Time What string } func (e MyError) Error() string { return fmt.Sprintf("%v: %v", e.When, e.What) } func oops() error { return MyError{ time.Date(1989, 3, 15, 22, 30, 0, 0, time.UTC), "the file system has gone away", } } func Example() { if err := oops(); err != nil { fmt.Println(err) } // Output: 1989-03-15 22:30:00 +0000 UTC: the file system has gone away }