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("程式結束")
}
複制