go-day4

作者: 码农工号9527 | 来源:发表于2022-11-26 00:06 被阅读0次

    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

          本文链接:https://www.haomeiwen.com/subject/yqiqfdtx.html