2246 字
11 分钟
01、
01、
// 类型断言
func main() { var a interface{} // 定义一个空接口变量a
a = 100 fmt.Printf("%T\n", a) // 如何判断a保存的值的具体类型是什么? // 类型断言 // 1. x.(T) v1, ok := a.(int8) if ok { fmt.Println("猜对了,a是int8", v1) } else { fmt.Println("猜错了,不是int8") }
// 2. switch switch v2 := a.(type) { case int8:
fmt.Println("int8", v2) case int16: fmt.Println("int16", v2) case string: fmt.Println("string", v2) case int: fmt.Println("int", v2) default: fmt.Println("滚~") }}02、
// 文件操作
func f1() { var fileObj *os.File var err error fileObj, err = os.Open("./xxx.go") defer fileObj.Close() if err != nil { fmt.Printf("open file failed, err:%v", err) return }}
func f11() { var fileObj *os.File var err error fileObj, err = os.Open("./main.go") if err != nil { fmt.Printf("open file failed, err:%v", err) return } defer fileObj.Close()}
func f2() { // 打开要操作的文件 fileObj, err := os.OpenFile("./sb.txt", os.O_RDWR, 0644) if err != nil { fmt.Printf("open file failed, err:%v\n", err) return } // 因为没有办法直接在文件中间插入内容,所以要借助一个临时文件 tmpFile, err := os.OpenFile("./sb.tmp", os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0644) if err != nil { fmt.Printf("create tmp file failed, err:%v\n", err) return } defer tmpFile.Close() // 读取源文件写入临时文件 var ret [1]byte n, err := fileObj.Read(ret[:]) if err != nil { fmt.Printf("read from file failed, err:%v", err) return } // 写入临时文件 tmpFile.Write(ret[:n]) // 再写入要插入的内容 var s []byte s = []byte{'c'} tmpFile.Write(s) // 紧接着把源文件后续的内容写入临时文件 var x [1024]byte for { n, err := fileObj.Read(x[:]) if err == io.EOF { tmpFile.Write(x[:n]) break } if err != nil { fmt.Printf("read from file failed, err:%v\n", err) return } tmpFile.Write(x[:n]) } // 源文件后续的也写入了临时文件中 fileObj.Close() tmpFile.Close() os.Rename("./sb.tmp", "./sb.txt")}
func main() { // f1() f2()}03、
// 时间
func f1() { now := time.Now() fmt.Println(now) fmt.Println(now.Year()) fmt.Println(now.Month()) fmt.Println(now.Day()) fmt.Println(now.Date()) fmt.Println(now.Hour()) fmt.Println(now.Minute()) fmt.Println(now.Second()) // 时间戳 fmt.Println(now.Unix()) fmt.Println(now.UnixNano()) // time.Unix() ret := time.Unix(1564803667, 0) fmt.Println(ret) fmt.Println(ret.Year()) fmt.Println(ret.Day()) // 时间间隔 fmt.Println(time.Second) // now + 24小时 fmt.Println(now.Add(24 * time.Hour)) // Sub 两个时间相减 nextYear, err := time.Parse("2006-01-02 15:04:05", "2019-08-04 12:25:00") if err != nil { fmt.Printf("parse time failed, err:%v\n", err) return } now = now.UTC() d := nextYear.Sub(now) fmt.Println(d) fmt.Println("------------------------") // 定时器 // timer := time.Tick(time.Second) // for t := range timer { // fmt.Println(t) // 1秒钟执行一次 // }
// 格式化时间 把语言中时间对象 转换成字符串类型的时间 // 2019-08-03 fmt.Println(now.Format("2006-01-02")) // 2019/02/03 11:55:02 fmt.Println(now.Format("2006/01/02 15:04:05")) // 2019/02/03 11:55:02 AM fmt.Println(now.Format("2006/01/02 03:04:05 PM")) // // 2019/02/03 11:55:02.342 fmt.Println(now.Format("2006/01/02 15:04:05.000")) // 按照对应的格式解析字符串类型的时间 timeObj, err := time.Parse("2006-01-02", "2019-08-03") if err != nil { fmt.Printf("parse time failed, err:%v\n", err) return } fmt.Println(timeObj) fmt.Println(timeObj.Unix())
// Sleep n := 5 // int fmt.Println("开始sleep了") time.Sleep(time.Duration(n) * time.Second) fmt.Println("5秒钟过去了") // time.Sleep(5 * time.Second)}
// 时区func f2() { now := time.Now() // 本地的时间 fmt.Println(now) // 明天的这个时间 // 按照指定格式取解析一个字符串格式的时间 time.Parse("2006-01-02 15:04:05", "2019-08-04 14:41:50") // 按照东八区的时区和格式取解析一个字符串格式的时间 // 根据字符串加载时区 loc, err := time.LoadLocation("Asia/Shanghai") if err != nil { fmt.Printf("load loc failed, err:%v\n", err) return } // 按照指定时区解析时间 timeObj, err := time.ParseInLocation("2006-01-02 15:04:05", "2019-08-04 14:41:50", loc) if err != nil { fmt.Printf("parse time failed, err:%v\n", err) return } fmt.Println(timeObj) // 时间对象相减 td := timeObj.Sub(now) fmt.Println(td)}
func main() { // f1() f2()}04、
// log demo
func main() { fileObj, err := os.OpenFile("./xx.log", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { fmt.Printf("open file failed, err:%v\n", err) return } log.SetOutput(fileObj)
for { log.Println("这是一条测试的日志") time.Sleep(time.Second * 3) }}05、
var log mylogger.Logger // 声明一个全局的接口变量
// 测试我们自己写 的日志库func main() { log = mylogger.NewConsoleLogger("Info") // 终端日志实例 log = mylogger.NewFileLogger("Info", "./", "zhoulinwan.log", 10*1024*1024) // 文件日志实例
for { log.Debug("这是一条Debug日志") log.Info("这是一条info日志") log.Warning("这是一条warning日志") id := 10010 name := "理想" log.Error("这是一条Error日志,id:%d,name:%s", id, name) log.Fatal("这是一条Fatal日志") // time.Sleep(2 * time.Second) }}06、
// runtime.Caller()
func f() { pc, file, line, ok := runtime.Caller(1) if !ok { fmt.Printf("runtime.Caller() failed\n") return } funcName := runtime.FuncForPC(pc).Name() fmt.Println(funcName) fmt.Println(file) // 01runtime_demo/main.go fmt.Println(path.Base(file)) fmt.Println(line) // 11}
func f1() { f()}
func main() { f1()}07、
// 1. 文件对象的类型// 2. 获取文件对象的详细信息
func main() { fileObj, err := os.Open("D:/test.txt") if err != nil { fmt.Printf("open file failed,err:%v\n", err) return } // 1. 文件对象的类型 fmt.Printf("%T\n", fileObj) // 2. 获取文件对象的详细信息 fileInfo, err := fileObj.Stat() if err != nil { fmt.Printf("get file info failed,err:%v\n", err) return } fmt.Printf("文件大小是:%dB\n", fileInfo.Size()) fmt.Printf("文件名是:%s\n", fileInfo.Name())}08、
// jsontype person struct { Name string `json:"name"` Age int `json:"age"`}
func main() { str := `{"name":"周林","age":9000}` var p person json.Unmarshal([]byte(str), &p) fmt.Println(p.Name, p.Age)}09、
type Cat struct {}
func reflectType(x interface{}) { v := reflect.TypeOf(x) fmt.Printf("type:%v\n", v) fmt.Printf("type name:%v type kind:%v\n", v.Name(), v.Kind())}
func reflectValue(x interface{}) { v := reflect.ValueOf(x) k := v.Kind() // 值的类型种类 switch k { case reflect.Int64: // v.Int()从反射中获取整型的原始值,然后通过int64()强制类型转换 fmt.Printf("type is int64, value is %d\n", int64(v.Int())) case reflect.Float32: // v.Float()从反射中获取整型的原始值,然后通过float32()强制类型转换 fmt.Printf("type is float32, value is %f\n", float32(v.Float())) case reflect.Float64: // v.Float()从反射中获取整型的原始值,然后通过float64()强制类型转换 fmt.Printf("type is float64, value is %f\n", float64(v.Float())) }}
// 通过反射设置变量的值func reflectSetValue1(x interface{}) { v := reflect.ValueOf(x) if v.Kind() == reflect.Int64 { v.SetInt(200) //修改的是副本,reflect包会引发panic }}
func reflectSetValue2(x interface{}) { v := reflect.ValueOf(x) if v.Elem().Kind() == reflect.Int64 { v.Elem().SetInt(200) //修改的是副本,reflect包会引发panic }}
func main() { var a float32 = 3.14 reflectType(a) // type:float32 var b int64 = 100 reflectType(b) // type:int64 var c = Cat{} reflectType(c) // ValueOf reflectValue(a) // 设置值 // reflectSetValue1(&b) reflectSetValue2(&b) fmt.Println(b)}10、
import ( "fmt" "reflect")
type student struct { Name string `json:"name" zhoulin:"嘿嘿嘿"` Score int `json:"score" zhoulin:"哈哈哈"`}
func main() { stu1 := student{ Name: "小王子", Score: 90, }
t := reflect.TypeOf(stu1)
fmt.Println(t.Name(), t.Kind()) // student struct
// 通过for循环遍历结构体的所有字段信息 fmt.Println(t.NumField()) // 2 for i := 0; i < t.NumField(); i++ { field := t.Field(i) fmt.Printf("name:%s index:%d type:%v json tag:%v\n", field.Name, field.Index, field.Type, field.Tag.Get("zhoulin")) }
// 通过字段名获取指定结构体字段信息 if scoreField, ok := t.FieldByName("Score"); ok { fmt.Printf("name:%s index:%d type:%v json tag:%v\n", scoreField.Name, scoreField.Index, scoreField.Type, scoreField.Tag.Get("json")) }}11、
// ini配置文件解析器
// MysqlConfig MySQL配置结构体type MysqlConfig struct { Address string `ini:"address"` Port int `ini:"port"` Username string `ini:"username"` Password string `ini:"password"`}
func loadIni(v interface{}) {
}
func main() { var mc MysqlConfig loadIni(&mc) fmt.Println(mc.Address, mc.Port, mc.Username, mc.Password)}12、
"mylogger")
// 测试我们自己写 的日志库func main() { // log := mylogger.NewLog("Info") log := mylogger.NewFileLogger("Info", "./", "zhoulinwan.log", 10*1024*1024) for {
log.Debug("这是一条Debug日志") log.Info("这是一条info日志") log.Warning("这是一条warning日志") id := 10010 name := "理想" log.Error("这是一条Error日志,id:%d,name:%s", id, name) log.Fatal("这是一条Fatal日志") time.Sleep(2 * time.Second) }}mylogger框架: console.go
// 往终端写日志相关内容
// Logger 日志结构体type ConsoleLogger struct { Level LogLevel}
// NewLog 构造函数func NewLog(levelStr string) ConsoleLogger { level, err := parseLogLevel(levelStr) if err != nil { panic(err) } return ConsoleLogger{ Level: level, }}
func (c ConsoleLogger) enable(logLevel LogLevel) bool { return logLevel >= c.Level}
func (c ConsoleLogger) log(lv LogLevel, format string, a ...interface{}) { if c.enable(lv) { msg := fmt.Sprintf(format, a...) now := time.Now() funcName, fileName, lineNo := getInfo(3) fmt.Printf("[%s] [%s] [%s:%s:%d] %s\n", now.Format("2006-01-02 15:04:05"), getLogString(lv), fileName, funcName, lineNo, msg) }}
func (c ConsoleLogger) Debug(format string, a ...interface{}) { c.log(DEBUG, format, a...)}
func (c ConsoleLogger) Info(format string, a ...interface{}) { c.log(INFO, format, a...)}
func (c ConsoleLogger) Warning(format string, a ...interface{}) { c.log(WARNING, format, a...)}
func (c ConsoleLogger) Error(format string, a ...interface{}) { c.log(ERROR, format, a...)}func (c ConsoleLogger) Fatal(format string, a ...interface{}) { c.log(FATAL, format, a...)}file.go
// 往文件里面写日志相关代码
type FileLogger struct { Level LogLevel filePath string // 日志文件保存的路径 fileName string // 日志文件保存的文件名 fileObj *os.File errFileObj *os.File maxFileSize int64}
// NewFileLogger 构造函数func NewFileLogger(levelStr, fp, fn string, maxSize int64) *FileLogger { logLevel, err := parseLogLevel(levelStr) if err != nil { panic(err) } fl := &FileLogger{ Level: logLevel, filePath: fp, fileName: fn, maxFileSize: maxSize, } err = fl.initFile() // 按照文件路径和文件名将文件打开 if err != nil { panic(err) } return fl}
func (f *FileLogger) initFile() error { fullFileName := path.Join(f.filePath, f.fileName) fileObj, err := os.OpenFile(fullFileName, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { fmt.Printf("open log file failed, err:%v\n", err) return err } errFileObj, err := os.OpenFile(fullFileName+".err", os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644) if err != nil { fmt.Printf("open err log file failed, err:%v\n", err) return err } // 日志文件都已经打开了 f.fileObj = fileObj f.errFileObj = errFileObj return nil}
func (f *FileLogger) enable(logLevel LogLevel) bool { return logLevel >= f.Level}
func (f *FileLogger) log(lv LogLevel, format string, a ...interface{}) { if f.enable(lv) { msg := fmt.Sprintf(format, a...) now := time.Now() funcName, fileName, lineNo := getInfo(3) fmt.Fprintf(f.fileObj, "[%s] [%s] [%s:%s:%d] %s\n", now.Format("2006-01-02 15:04:05"), getLogString(lv), fileName, funcName, lineNo, msg) if lv >= ERROR { // 如果要记录的日志大于等于ERROR级别,我还要在err日志文件中再记录一遍 fmt.Fprintf(f.errFileObj, "[%s] [%s] [%s:%s:%d] %s\n", now.Format("2006-01-02 15:04:05"), getLogString(lv), fileName, funcName, lineNo, msg) } }}
func (f *FileLogger) Debug(format string, a ...interface{}) { f.log(DEBUG, format, a...)}func (f *FileLogger) Info(format string, a ...interface{}) { f.log(INFO, format, a...)}
func (f *FileLogger) Warning(format string, a ...interface{}) { f.log(WARNING, format, a...)
}
func (f *FileLogger) Error(format string, a ...interface{}) { f.log(ERROR, format, a...)
}func (f *FileLogger) Fatal(format string, a ...interface{}) { f.log(FATAL, format, a...)
}
func (f *FileLogger) Close() { f.fileObj.Close() f.errFileObj.Close()}mylogger.go// 自定义一个日志库
type LogLevel uint16
const ( UNKNOWN LogLevel = iota DEBUG TRACE INFO WARNING ERROR FATAL)
func parseLogLevel(s string) (LogLevel, error) { s = strings.ToLower(s) switch s { case "debug": return DEBUG, nil case "trace": return TRACE, nil case "info": return INFO, nil case "warning": return WARNING, nil case "error": return ERROR, nil case "fatal": return FATAL, nil default: err := errors.New("无效的日志级别") return UNKNOWN, err }}
func getLogString(lv LogLevel) string { switch lv { case DEBUG: return "DEBUG" case TRACE: return "TRACE" case INFO: return "INFO" case WARNING: return "WARNING" case ERROR: return "ERROR" case FATAL: return "FATAL" } return "DEBUG"}
func getInfo(skip int) (funcName, fileName string, lineNo int) { pc, file, lineNo, ok := runtime.Caller(skip) if !ok { fmt.Printf("runtime.Caller() failed\n") return } funcName = runtime.FuncForPC(pc).Name() fileName = path.Base(file) funcName = strings.Split(funcName, ".")[1] return}