9.1反射
在Go语言标准库中reflect包提供了运行时反射,程序运行过程中动态操作结构体
当变量存储结构体属性名称,想要对结构体这个属性赋值或查看时,就可以使用反射
反射还可以用作判断变量类型
整个reflect包中最重要的两个类型
- reflect.Type类型
- reflect.Value值
获取到Type和Value的函数
- reflect.TypeOf(interface{})返回type
- reflect.ValueOf(interface{})返回值Value
(1)获取变量属性和值
//Learn_Go/main.go package main import ( "fmt" "reflect" ) func main() { a := 1.5 fmt.Println(reflect.TypeOf(a)) //float64 fmt.Println(reflect.ValueOf(a)) //1.5 }
(2)获取结构体属性的值
//Learn_Go/main.go package main import ( "fmt" "reflect" ) type People struct { name string address string } func main() { peo := People{"derek","guangdong"} v := reflect.ValueOf(peo) //有多少个字段 fmt.Println(v.NumField()) //2 //根据索引获取字段值 fmt.Println(v.FieldByIndex([]int {0})) //derek content := "address" fmt.Println(v.FieldByName(content)) //guangdong }
(3)设置结构体属性的值
反射时获取peo的地址,Elem()获取指针指向地址的封装
//Learn_Go/main.go package main import ( "fmt" "reflect" ) type People struct { Name string Address string } func main() { content := "Name" peo := new(People) //Elem()获取指针对应元素的值 v := reflect.ValueOf(peo).Elem() //CanSet():判断值有没有被设置,有设置:True,没有设置:false fmt.Println(v.FieldByName(content).CanSet()) //需要修改属性的内容时,要求结构体中属性名首字母大写才可以设置 v.FieldByName(content).SetString("alice") v.FieldByName("Address").SetString("beijing") fmt.Println(peo) //&{alice beijing} }
(4)结构体支持标记(tag),标记通常都是通过反射技术获取到
//Learn_Go/main.go package main import ( "fmt" "reflect" ) type People struct { Name string `xml:"name"` Address string } func main() { t := reflect.TypeOf(People{}) fmt.Println(t.FieldByName("Name")) //{Name string xml:"name" 0 [0] false} true name,_ := t.FieldByName("Name") fmt.Println(name.Tag) //xml:"name" fmt.Println(name.Tag.Get("xml")) //name }
9.2.日志
有三种级别日志输出
- Print() 输出日志信息
- Panic()打印日志信息,并处罚panic,日志信息为Panic信息
- Fatal()打印日志信息后调用os.Exit(0)
所有日志信息打印时都带有时间,且颜色为红色,输出日志信息到文件中
//Learn_Go/main.go package main import ( "log" "os" ) func main() { f,_ := os.OpenFile("D:/golog.log",os.O_APPEND|os.O_CREATE,0777) logger := log.New(f,"[Info]",log.Ltime) //"[Info]":prefix string logger.Println("打印日志信息") //[Info]22:13:59 打印日志信息 }
9.3.线程休眠和延迟执行
(1)线程休眠
Go语言中main()函数为主线程(协程),程序是从上向下执行的
可以通过time包下的Sleep(n)让程序阻塞多少纳秒
//Learn_Go/main.go package main import ( "fmt" "time" ) func main() { fmt.Println("111") time.Sleep(2e9) //2e9 相当于2秒 fmt.Println("222") }
(2)延迟执行
延迟指定时间后执行一次,但是需要注意在触发时程序没有结束
//Learn_Go/main.go package main import ( "fmt" "time" ) func main() { fmt.Println("程序开始") time.AfterFunc(3e9, func() { fmt.Println("延迟执行") }) time.Sleep(4e9) //必须阻塞4s,要不主程序执行完直接退出,不会执行“延迟执行”的代码 fmt.Println("程序结束") }