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、#

// json
type 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
}
01、
https://blog.zhequtao.com/posts/golang/go-new/base/base06/
作者
阿俊
发布于
2020-03-30
许可协议
CC BY-NC-SA 4.0

相关阅读