iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 16
1

time

時間計算是頗複雜的一件事情,只能挑一些常用來說明

1.取得現在時間,這時區是根據執行這段語法的主機,所以主機如果設定成UTC就會呈現UTC的時間

current := time.Now()
//2020-09-22 11:50:21.646586 +0800 CST m=+0.000084078

2.取得時間的timestamp

st := time.Now().Unix()
//1600746812

3.timestamp轉回time格式

d := time.Unix(1600746812, 0)
//2020-09-22 11:55:51 +0800 CST

4.取得year,month,day的數值

y, m, d := time.Now().Date()
//這時侯的m是time.month型態,所以如果要換成int的話,直接用int(m)處理就可以
//2020 September 22

5.取得hour,min,sec的數值

h := time.Now().Hour()
m := time.Now().Minute()
s := time.Now().Second()
//hour:13 minute:53 second:55

6.數值轉成time

qq := time.Date(2020, 9, 20, 0, 0, 0, 0, time.Local)
//2020-09-20 00:00:00 +0800 CST

7.format,golang的format格式有點奇妙.. 有興趣可以看一下這篇文章 2006-01-02 15:04:05

qq := time.Now().Format("2006-01-02 15:04:05") 
//2020-09-20 15:23:10

要如何轉成指定時區的時間呢,可以透過time.LoadLocation進行轉換,比使用單純的加減時間準確

package main

import (
	"fmt"
	"time"
)

func main() {
	t := time.Now()
	var localLocation *time.Location
	var err error
    //設定時區為UTC
	localLocation, err = time.LoadLocation("UTC")
	if err != nil {
		return
	}
    //t.In(localLocation) local時區轉換成utc時區
	fmt.Println("utc timestamp:", t.In(localLocation).Unix(), "local time:", t.In(localLocation), "utc time:", t)
    //utc timestamp: 1600754558 local time: 2020-09-22 06:02:38.612689 +0000 UTC utc time: 2020-09-22 14:02:38.612689 +0800 CST m=+0.000082078
}
    //取得今天的0點0分 timestamp
    y, m, d := t.Date()
	utc := time.Date(y, m, d, 0, 0, 0, 0, localLocation).Unix()
	local := time.Date(y, m, d, 0, 0, 0, 0, time.Local).Unix()
    //local: 1600704000 utc: 1600732800

時間的計算

package main

import (
	"fmt"
	"time"
)

func main() {
	//計算start到end花了多少時間,可以拿來計算func執行多久
	start := time.Now()
	//也可以寫這樣子 time.Sleep(time.Duration(5) * time.Second)
	time.Sleep(5 * time.Second)
	end := time.Since(start)
	fmt.Println(end) 
    
   //Add 時間加上特定時間後的時間
	add := start.Add(5 * time.Second)
	fmt.Println("before:", start, "after:", add)
	//before: 2020-09-22 14:31:40.656482 +0800 CST m=+0.000087995 after: 2020-09-22 14:31:45.656482 +0800 CST m=+5.000087995
	
	//二個時間的差距
	start2 := start.Add(-5 * time.Second)
	sub := start.Sub(start2)
	fmt.Println(sub)
	//5s
}

ticker

可以當成是個定時器,每n時間執行什麼事情

package main

import (
	"fmt"
	"time"
)

func main() {
	d := time.Duration(time.Second * 2)
	//設定一個ticker,每二秒
	t := time.NewTicker(d)
	defer t.Stop()
	var count = 0
	for {
		<-t.C
		if count == 10 {
			fmt.Println("stop do something")
			t.Stop()
			break
		}
		fmt.Println("do something")
		count++
	}
}

JSON

golang原生對json的操作是主要有二個
1.Marshal:把struct轉成[]byte
2.Unmarshal:把[]byte轉成struct,官方有段註解說明對應的型態

// To unmarshal JSON into an interface value,
// Unmarshal stores one of these in the interface value:
//
//	bool, for JSON booleans
//	float64, for JSON numbers
//	string, for JSON strings
//	[]interface{}, for JSON arrays
//	map[string]interface{}, for JSON objects
//	nil for JSON null
package main

import (
	"encoding/json"
	"fmt"
)

type ColorGroup struct {
	ID     int
	Name   string
	Colors []string
}

const test = `
{"ID":2,"Name":"QQ","Colors":["A","B","C","D"]}
`

func main() {
	//Marshal:struct to []byte
	group := ColorGroup{
		ID:     1,
		Name:   "Reds",
		Colors: []string{"Crimson", "Red", "Ruby", "Maroon"},
	}
    //把struct轉成[]byte
	b, err := json.Marshal(group)
	if err != nil {
		fmt.Println("error:", err)
	}
	fmt.Println(b, string(b))

	var g ColorGroup
    //把json轉到strcut
	err3 := json.Unmarshal([]byte(test), &g)
	if err3 != nil {
		fmt.Println("error3:", err3)
	}
	fmt.Println("g:", g)
}

如果會大量使用到Marshal/Unmarshal或是json object很巨大,又對效能很敏感的話,可以考慮使用這套件
json-iterator,使用方案跟原生的一樣,可以無痛接軌XD

import jsoniter "github.com/json-iterator/go"
//記得把"encoding/json"原生套件移除

var json = jsoniter.ConfigCompatibleWithStandardLibrary
//宣告一個全域變動json的物件,這樣子就可以使用json.Marshal/json.Unmarshal

json object操作

這邊有二個套件推薦,可以視情形選擇使用
1.jsonparser:優點,抓取的path裡面文字有包含標號.時不會被影響到,ex mail或是ip
2.gjson:主要優點是可以用類似正則式的方式去操作,缺點是他的path是用.來分割,所以遇到key值是mail或是ip這類格式的資料時就會走鐘,抓成下層結點。

logger

原生的logger僅能輸出文件字串,如果需要搭配elk這一類的日誌分析軟體去做更進一步的資料鑽研,
可以考慮使用json格式輸出的logrus

go get github.com/sirupsen/logrus

如果沒設定輸出格式的話還是會呈現預設ASCII formatter

package main

import (
	log "github.com/sirupsen/logrus"
)

func main() {
	log.WithFields(log.Fields{
		"animal": "walrus",
		"size":   10,
	}).Info("A group of walrus emerges from the ocean")
    //INFO[0000] A group of walrus emerges from the ocean      animal=walrus size=10
}

需要先設定JSONFormatter,這樣子才能輸出成json格式的log

package main

import (
	"os"
	log "github.com/sirupsen/logrus"
)

func init() {
	// Log as JSON instead of the default ASCII formatter.
	log.SetFormatter(&log.JSONFormatter{})
	// Output to stdout instead of the default stderr
	// Can be any io.Writer, see below for File example
	log.SetOutput(os.Stdout)
	// Only log the warning severity or above.
	log.SetLevel(log.InfoLevel)
}

func main() {
	log.WithFields(log.Fields{
		"animal": "walrus",
		"size":   10,
	}).Info("A group of walrus emerges from the ocean")

	log.WithFields(log.Fields{
		"omg":    true,
		"number": 122,
	}).Warn("The group's number increased tremendously!")
    //{"animal":"walrus","level":"info","msg":"A group of walrus emerges from the ocean","size":10,"time":"2020-09-22T17:21:21+08:00"}
//{"level":"warning","msg":"The group's number increased tremendously!","number":122,"omg":true,"time":"2020-09-22T17:21:21+08:00"}
	
}


上一篇
[DAY15]golang常用套件(字串類與型態轉換)
下一篇
[DAY17]動手做個http服務吧~~
系列文
欸你這週GO了嘛30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言