time标准库
时间类型 time.Time
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))
定时器
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())
1564804613962.png
1564814836624.png
反射
反射的应用
json
反序列化就是反射的应用。
{"name:"zhoulin", "age":9000}
type person struct {
Name string ``
}
反射的两个方法
reflect.TypeOf
和reflect.ValueOf
type又分为Name()
,Kind()
package main
import (
"fmt"
"reflect"
)
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)
}
结构体反射
package main
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"))
}
}
并发
记住并发和并行的区别
goroutine
goroutine
是用户态的线程,比内核态线程更轻量级,是由Go语言的运行时(runtime)调度的。
启动goroutine
// goroutine
func hello(i int) {
fmt.Println("hello", i)
}
// 程序启动之后会创建一个主goroutine去执行
func main() {
for i := 0; i < 100; i++ {
go hello(i) // 开启一个单独的goroutine去执行hello函数(任务)
}
fmt.Println("main")
time.Sleep(time.Second)
// main函数结束了 由main函数启动的goroutine也都结束了
}
goroutine
什么结束?
goroutine 对应的函数结束了,goroutine结束了。
main
函数执行完了,由main
函数创建的那些goroutine
都结束了。
math/rand
func f() {
rand.Seed(time.Now().UnixNano()) // 保证每次执行的时候都有点不一样
for i := 0; i < 5; i++ {
r1 := rand.Int() // int64
r2 := rand.Intn(10) // 0<= x < 10
fmt.Println(r1, r2)
}
}
goroutine
调度模型
GMP
M:N
:把m个goroutine分配给n个操作系统线程去执行.
goroutine初始栈的大小是2k.
channel
var b chan int // 需要指定通道中元素的类型
通道必须使用make函数初始化才能使用!!!
通道的操作
<-
- 发送 :
ch1 <- 1
- 接收:
<- ch1
- 关闭:
close()
带缓冲的通道和无缓冲的通道
无缓冲的通道要想发送值,必须有人接收。--》4x100接力传接棒
单向通道
多用于函数传参,限制函数中通道的操作。
work pool
goroutine
池
select多路复用
select一般是和chan一起工作的,用于同时监听多个chan的信息
select {
case <-ch1:
// ...
case x := <-ch2:
// ...
case ch3 <- y:
// ...
default :
// ...
}
网友评论