内容简介: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,接口如下:
Go语言开发(十一)、 Go 语言常用标准库一
一、log
1、log模块简介
Go语言中log模块用于在程序中输出日志。
log模块提供了三类日志输出接口,Print、Fatal和Panic。Print是普通输出;Fatal是在执行完Print后,执行 os.Exit(1);Panic是在执行完Print后调用panic()方法。log模块对每一类接口其提供了3中调用方式,分别是"Xxxx、 Xxxxln、Xxxxf"。
2、log.Print接口
log.Print类接口包括log.Print、log.Println、log.Printf,接口如下:
// 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类接口使用示例:
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]
3、log.Fatal接口
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接口使用示例:
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接口调用会导致程序退出。
4、log.Panic接口
log.Panic类接口包括log.Panic、log.Panicln、log.Panicf,接口如下:
// 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不会执行。
5、logger定制
Logger是写入日志的基本组件,log模块中存在一个标准Logger,可以直接通过log进行访问,可以直接使用log.xxxx进行日志进行输出。但在实际使用中,不同类型的日志可能拥有需求,仅标准Logger不能满足日志记录的需求,通过创建不同的Logger可以将不同类型的日志分类输出。使用logger前需要首先通过New函数创建一个Logger对象,函数声明如下:
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
6、log分级日志实现
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、支持输出文件名行号,以及时间、日志界别
二、regexp
1、regexp简介
Go语言通过regexp标准包为正则表达式提供了官方支持。在Go语言环境中可以使用下列命令查看正则表达式的语法:
go doc regexp/syntax
2、Regexp正则对象
Regexp是一个编译好的正则表达式对象。
type Regexp struct {
// read-only after Compile
regexpRO
// cache of machines for running regexp
mu sync.Mutex
machine []*machine
}
通常需要使用正则表达式构建一个正则对象
3、regexp常用接口
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
将正则表达式编译成一个正则对象,但会在解析失败时panic
func (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。
4、regexp示例
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
1、strconv简介
strconv提供了字符串与基本类型的转换函数接口。
2、字符串与bool类型转换
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
}
3、字符串与整型转换
func ParseInt(s string, base int, bitSize int) (i int64, err error)
ParseInt将字符串转换为int类型
s:要转换的字符串
base:进位制(2进制到36进制)
bitSize:指定整数类型(0:int、8:int8、16:int16、32:int32、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。
4、字符串与浮点型转换
func ParseFloat(s string, bitSize int) (f float64, err error)
ParseFloat将字符串转换为浮点数,
s:要转换的字符串
bitSize:指定浮点类型(32:float32、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:float32、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
}
5、特殊字符处理函数
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
1、time简介
time包提供显示和计算时间用的函数。Go中时间处理依赖的数据类型: time.Time, time.Month, time.Weekday, time.Duration, time.Location。
2、time.Time时间点
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) {} // 时间序列化
3、 time.Month月份
time.Month 代表一年中的某个月
type Month int const ( January Month = 1 + iota February March April May June July August September October November December )
4、time.Weekday星期
time.Weekday 代表一周的周几
type Weekday int const ( Sunday Weekday = iota Monday Tuesday Wednesday Thursday Friday Saturday )
5、time.Duration时间段
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 // 将时间段表示为小时
6、time.Locations时区
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
7、其它接口
func Sleep(d Duration)
阻塞当前go协程至少d代表的时间段。d<=0时,Sleep会立刻返回。
五、errors
1、errors简介
Go语言使用error类型来返回函数执行过程中遇到的错误,如果返回error值为nil,则表示未遇到错误,否则error会返回一个字符串。error是一个预定义标识符,代表一个Go语言內建的接口类型,任何自定义的错误类型都要实现Error接口函数。
type error interface {
Error() string
}
2、error常用接口
func New(text string) error
将字符串text包装成一个error对象返回
import (
"errors"
"fmt"
)
var ErrUnexpectedEOF = errors.New("unexpected EOF")
func main() {
fmt.Println(ErrUnexpectedEOF)
}
3、error定制
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
}
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 区块链技术语言(三十):Go语言常用工具包
- Go语言开发(十三)、Go语言常用标准库三
- Go语言开发(十四)、Go语言常用标准库四
- Go语言开发(十五)、Go语言常用标准库五
- Go语言开发(十六)、Go语言常用标准库六
- ASP程序中常用的脚本语言
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Probability and Computing
Michael Mitzenmacher、Eli Upfal / Cambridge University Press / 2005-01-31 / USD 66.00
Assuming only an elementary background in discrete mathematics, this textbook is an excellent introduction to the probabilistic techniques and paradigms used in the development of probabilistic algori......一起来看看 《Probability and Computing》 这本书的介绍吧!