天天看點

9.Go-反射、日志和線程休眠

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

複制