go-day4

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.TypeOfreflect.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函数初始化才能使用!!!

通道的操作

<-

  1. 发送 : ch1 <- 1
  2. 接收: <- ch1
  3. 关闭:close()

带缓冲的通道和无缓冲的通道

无缓冲的通道要想发送值,必须有人接收。--》4x100接力传接棒

单向通道

多用于函数传参,限制函数中通道的操作。

work pool

goroutine

1565433376430.png

select多路复用

select一般是和chan一起工作的,用于同时监听多个chan的信息

select {
case <-ch1:
// ...
case x := <-ch2:
// ...
case ch3 <- y:
// ...
default :
// ...
}

你可能感兴趣的:(go-day4)