zoukankan      html  css  js  c++  java
  • DAY 101 go05

     

    1w字---》技能点,项目
    自我介绍 5--6分钟(你的个人介绍,以及一个项目的详细介绍)
    面试套路,不会的问题作何反应,面试最后的收尾

    五险一金

     1 字符串

        -utf-8
       -字节长度(len),字符长度(utf8包下)
       -for循环迭代循环(字符),索引循环(字节)
       
    2 指针
    -& 放在变量前,表示取该变量的地址
       -* 放在变量前,表示解引用
       -* 放在类型前,表示指向这个类型的指针
       
       -零值:nil
       -向函数传递指针参数
      -(*a)
       -不支持指针运算
       
       -数组指针,指针数组
       
       
    3 结构体:一系列属性(字段)的集合
    -结构: type 名字 struct{
          属性1 类型
          属性2 类型
      }
      -匿名结构体:type 名字都省略
      -用在内部,只使用一次
      -结构体零值:值类型,当作参数传递,修改不会影响原来的
       -访问结构体字段:通过 .
       -导出字段:首字母是否是大写
       -结构体指针
       -匿名字段:字段没有名字,类型名就是字段名----》提升字段
       -结构体嵌套:结构体中套结构体(有名结构体,匿名结构体)
       -如果嵌套的结构体是匿名,这个结构体的字段会被提升:
       -结构体嵌套类似于---继承
       -结构体相等性:所有字段可比较,结构体才可以比较
       

    1 方法

    1 函数和方法
    2 方法有特殊之处:绑定给谁,谁来调用,会把调用者自动传入

    3 go中如何写方法
    -方法其实就是一个函数,在 func 这个关键字和方法名中间加入了一个特殊的接收器类型。
       -接收器可以是结构体类型或者是非结构体类型。
       -接收器是可以在方法的内部访问的
    package main

    import "fmt"

    // 方法

    //type Address struct {
    // province string
    // city string
    //}
    //
    //func (a Address)printAddr() {
    // fmt.Println("省是:",a.province,"市是:",a.city)
    //}
    //
    //type Person struct {
    // name string
    // age int
    // Address // 匿名字段 结构体嵌套
    //
    //}
    //// 方法,方法是绑定给Person这个结构体的
    //// 值类型接收器
    //func (p Person) changName(name string) {
    // p.name=name
    // fmt.Println(p)
    //}
    //func (p Person)printAddr() {
    // p.Address.printAddr()
    // fmt.Println("Person的省是:",p.Address.province,"市是:",p.Address.city)
    //}
    //// 指针类型接收器
    //func (p *Person) changAge(age int) {
    // p.age=age
    //}
    //
    //// 普通函数
    //func changName(p Person) {
    // fmt.Println("名字被改了")
    // fmt.Println(p)
    //}


    // 6 在方法中使用值接收器 与 在函数中使用值参数 在方法中使用指针接收器 与 在函数中使用指针参数
    type Person struct {
    name string
    age int
    }
    //方法中使用值接收器
    func (p Person)changeName(name string) {
    p.name=name
    }
    // 在函数中使用值参数
    func changeName(p Person,name string) {
    p.name=name
    }

    //方法中使用指针收器
    func (p *Person)changeAge(age int) {
    p.age=age
    }
    // 在函数中使用指针
    func changeAge(p *Person,age int) {
    p.age=age
    }




    // 7 非结构体的方法(把原来的类型,重命名)
    type MyInt int

    func (i *MyInt)Add(){
    (*i)++
    }
    func main() {
    //1 方法的使用
    //p:=Person{"lqz",19}
    //p.changName() //自动传值

    //2 为什么有了函数还用方法
    //changName(p) // 调用函数
    //p.changName() //调用方法


    //3 指针接收器与值接收器
    //p:=&Person{"lqz",19}
    //p.changName("张三")
    //fmt.Println(p)
    //p.changAge(100)
    //fmt.Println(p)


    // 不管是值类型接收器还是指针类型接收器的方法,都可以使用值调用和指针调用
    // 决定结构体对象是否能被修改,是接收器决定的,如果是值类型接收器,就不改,如果是指针类型接收器就修改原来的

    //4 什么时候使用指针接收器,什么时候使用值接收器
    // 当拷贝一个结构体的代价过于昂贵时

    //5 匿名字段的方法(也会被提升)
    //p:=Person{"lqz",19,Address{"山东","潍坊"}}
    //p.printAddr()   // 匿名字段的方法也被提升
    //p.Address.printAddr()

    //6 不管是值类型接收器还是指针类型接收器的方法,都可以使用值调用和指针调用
    //在方法中使用值接收器 与 在函数中使用值参数
    // 在方法中使用指针接收器 与 在函数中使用指针参数
    //p:=Person{"lqz",19}
    ////p:=&Person{"lqz",19}
    ////p.changeName("egon") // 方法:无论是值还是指针,都可以来调用
    ////fmt.Println(p)
    ////changeName(p,"egon") // 函数:类型严格,必须传值类型
    //
    //p.changeAge(99) // 方法:无论是值还是指针,都可以来调用
    //changeAge(p,99) // 函数:类型严格,必须传指针类型


    // 7 非结构体上的方法
    var i MyInt=10
    var i1 int =10
    i.Add()
    i.Add()
    i.Add()
    i.Add()
    i.Add()
    fmt.Println(i)
    fmt.Println(i+MyInt(i1))  // 强类型,不同类型不能直接运算

    }

     

    2 接口

    package main

    import "fmt"

    // 接口:接口定义一个对象的行为,   鸭子类型

    /*
    在面向对象的领域里,接口一般这样定义:接口定义一个对象的行为。接口只指定了对象应该做什么,至于如何实现这个行为(即实现细节),则由对象本身去确定。
    在 Go 语言中,接口就是方法的集合。当一个类型实现了接口中的所有方法,我们称它实现了该接口
    接口指定了一个类型应该具有的方法,并由该类型决定如何实现这些方法
    */

    // 1 定义一个接口
    type Duck interface {
    speak()
    run()
    }

    // 定义一个TDuck结构体
    type TDuck struct {
    name string
    age int
    wife string
    }

    // 定义一个普通鸭子结构体
    type PDuck struct {
    name string
    age int
    }

    // 让TDuck实现Duck接口( 只要绑定接口中所有方法,就叫实现该接口)
    func (t TDuck)speak() {
    fmt.Printf("唐老鸭的名字是:%v,它说人话",t.name)
    }
    func (t TDuck)run() {
    fmt.Printf("唐老鸭的名字是:%v,它是人走路",t.name)
    }


    // 让PDuck实现Duck接口( 只要绑定接口中所有方法,就叫实现该接口)
    func (t PDuck)speak() {
    fmt.Printf("普通的名字是:%v,它嘎嘎叫",t.name)
    }
    func (t PDuck)run() {
    fmt.Printf("普通的名字是:%v,它走路歪歪妞妞",t.name)
    }



    // 定义一个空接口(所有类型都实现了空接口,空接口类型可以接收任意类型)
    type Empty interface {
    }


    func main() {
    // 1 接口的使用(接口也是一个类型)
    //var duck Duck // 定义一个Duck接口类型的变量
    //var tduck TDuck=TDuck{"egon",18,"迪丽热巴"}// 定义一个唐老鸭对象
    //var pduck PDuck=PDuck{"鸭子1号",1} // 定义一个普通鸭子对象
    //tduck.run()
    //tduck.speak()

    //pduck.run()
    //pduck.speak()

    //duck=tduck   //TDuck实现了Duck接口,就可以赋值给接口类型
    //duck.run()   // duck接口类型具体类型TDuck的run方法   //
    //duck.speak()


    //2 不考虑具体类型的情况下使用变量
    //var tduck TDuck=TDuck{"egon",18,"迪丽热巴"}
    //run(tduck)
    //var pduck PDuck=PDuck{"鸭子1号",1}
    //run(pduck)


    //3 类型断言(把接口类型,转成真正的具体类型)
    //var tduck Duck=TDuck{"egon",18,"迪丽热巴"}
    //test(tduck)

    //var pduck PDuck=PDuck{"鸭子1号",1}
    //test(pduck)

    // 4 空接口 (没有任何方法的接口)
    //var i Empty=10
    //var i Empty="lqz"
    //var i Empty=TDuck{"egon",19,"迪丽热巴"}
    //fmt.Println(i)

    //test2(10)

    // 5 匿名空接口 (省略type和接口名)
    //var i interface{}=88
    //fmt.Println(i)

    // 6 类型选择(使用switch,优雅的替换掉if-else)
    //var i interface{}=88
    //test3(i)
    //test3("lqz")
    test3(TDuck{"egon",19,"迪丽热巴"})


    }

    func run(d Duck) {
    d.run()
    }

    func test(d Duck) {
    // 断言出真正的类型(TDuck) v,ok:=变量.(类型)

    if v,ok:=d.(TDuck);ok{
    fmt.Printf(v.wife)
    }else if v,ok:=d.(PDuck);ok{
    fmt.Printf(v.name)
    }


    }

    func test2(i Empty) {
    fmt.Println(i)

    }

    func test3(i interface{}) {
    switch v:=i.(type) {
    case int:
    fmt.Println("我是int")

    case string:
    fmt.Println("我是字符串")

    case TDuck:
    fmt.Println("我是唐老鸭类型")
    //把唐老鸭的wife打印出来
    fmt.Println(v.wife)

    case PDuck:
    fmt.Println("我是一个普通鸭子类型")

    default:
    fmt.Println("不知道什么类型")




    }
    }
    package main

    import "fmt"

    // 接口其他:实现多个接口,接口嵌套,接口零值


    // 1 实现多个接口

    // 2 接口嵌套(继承)
    type Duck1 interface {
    speak()
    run()
    Animal  // 接口嵌套
    }
    //再定义一个Animal接口
    type Animal interface {
    eat()
    }


    // 定义一个TDuck1结构体,实现Duck1接口
    type TDuck1 struct {
    name string
    age int
    wife string
    }


    func (t TDuck1)speak() {
    fmt.Printf("唐老鸭的名字是:%v,它说人话",t.name)
    }
    func (t TDuck1)run() {
    fmt.Printf("唐老鸭的名字是:%v,它是人走路",t.name)
    }


    func (t TDuck1)eat() {
    fmt.Printf("吃饭")
    }

    func main() {
    // 1 实现多个接口
    //var a Animal=TDuck1{"egon",19,"dlrb"}
    //var b Duck1=TDuck1{"egon",19,"dlrb"}
    //a.eat()
    //b.speak()


    // 2 接口嵌套
    //var b Duck1=TDuck1{"egon",19,"dlrb"}

    // 3 接口零值:nil,接口是引用类型
    var b Duck1
    fmt.Println(b)  //<nil> 接口是引用类型
    }

     

    3 go routine

    package main

    import (
    "fmt"
    "time"
    )

    //goroutine:go 协程
    // 并发:在一个时间段内,执行多个任务
    // 并行(多核支持):同一时刻,执行多个任务

    /*
    Go 协程是与其他函数或方法一起并发运行的函数或方法。Go 协程可以看作是轻量级线程。
    与线程相比,创建一个 Go 协程的成本很小。因此在 Go 应用中,常常会看到有数以并千计的 Go 协程发地运行
    */


    //开启协程:线程+协程的混合体(不会开启进程)


    // 定义一个任务
    func task() {
    fmt.Println("go go go")
    }
    func task2() {
    fmt.Println("go2 go2 go2")
    }
    func main() {
    fmt.Println("开始了")
    go task()  //并发了
    //go task() //并发了
    //go task() //并发了
    go task2()  //并发了
    time.Sleep(1*time.Second)
    fmt.Println("结束了")

    // 睡1s,gogogo 一定会打印出来

    }

     

    4 信道,缓冲信道

    4.1 信道基础

    package main

    import (
    "fmt"
    "time"
    )

    // 信道:变量,不同go 协程之间通信的
    //信道可以想像成 Go 协程之间通信的管道。如同管道中的水会从一端流到另一端,通过使用信道,数据也可以从一端发送,在另一端接收

    func task3(c chan int) {

    fmt.Println("go go go")
    time.Sleep(1*time.Second)
    c<-100  //往里放
    //time.Sleep(1*time.Second)
    fmt.Println("放完了")
    }
    func main() {
    // 1 信道的定义和基本使用()
    //var c chan int // 定义了一个int类型的信道
    //var c chan int =make(chan int) // 定义并初始化
    ////往信道中放值
    //c <-1   // 走到这一句,程序就卡住了
    //// 从信道中取值
    ////<-c
    //var a int = <-c
    //fmt.Println(a)

    // 信道是引用类型,零值为nil


    // 2 发送与接收默认是阻塞的
    //var c chan int =make(chan int)
    //c <-1 //deadlock:死锁问题
    //<-c     //deadlock:死锁


    // 3 在一个goroutine中放值,另一个中取值
    //var c chan int =make(chan int)
    //go task3(c)
    ////var i int=<-c //往外取
    //i:=<-c //往外取
    //fmt.Println(i)
    //fmt.Println("执行结束了?")









    //2 借助信道,通道
    //fmt.Println("开始了吗?")
    //go task3()
    //// task3协程执行完以后,再继续往下执行
    //fmt.Println("结束了吗?")
    }

    4.2 信道操作

    package main

    // 4 信道的另一个例子: 通过并发计算一个数字的每一位:平方和+立方和
    //func calcSquares(number int, squareop chan int) {
    // sum := 0
    // for number != 0 {
    // digit := number % 10 // 589 % 20--->9
    // sum += digit * digit // sum+=9*9
    // number /= 10 // 58
    // }
    // squareop <- sum
    //}
    //
    //func calcCubes(number int, cubeop chan int) {
    // sum := 0
    // for number != 0 {
    // digit := number % 10
    // sum += digit * digit * digit
    // number /= 10
    // }
    // cubeop <- sum
    //}
    //
    //func main() {
    // number := 589
    // sqrch := make(chan int)
    // cubech := make(chan int)
    // go calcSquares(number, sqrch)
    // go calcCubes(number, cubech)
    //
    // squares, cubes := <-sqrch, <-cubech
    // //cubes := <-cubech
    // //squares := <-sqrch
    // fmt.Println("Final output", squares+cubes)
    //}



    // 5 单向信道(了解)
    //func sendData(sendch chan<- int) {
    // //<-sendch
    // sendch <- 10
    //}

    //func main() {
    // sendch := make(chan int)
    // go sendData(sendch)
    // fmt.Println(<-sendch)
    //}


    // 6 信道的关闭
    //func main() {
    // var a chan int =make(chan int)
    // //a<-1
    // //close(a)
    // //v,ok:=<-a
    // //fmt.Println(v,ok)
    //}

    // 7 关闭信道的案例
    func producer(chnl chan int) {
    for i := 0; i < 10; i++ {
    chnl <- i
    }
    close(chnl)
    }
    func main() {
    ch := make(chan int)
    go producer(ch)
    //for {
    // v, ok := <-ch
    // if ok == false {
    // break
    // }
    // fmt.Println("Received ", v, ok)
    //}
    //for v:=range ch{ // 通过range循环,如果信道没关闭,会一个个取值,如果信道关闭了,range之间结束
    // fmt.Println("Received ", v)
    //}
    }

     

    4.3 缓冲信道

    package main

    import (
    "fmt"
    )

    // 缓冲信道
    //func main() {
    // 1 定义一个有缓冲信道,定义一个缓冲大小为1的信道
    //var ch chan int=make(chan int,3)
    //var ch chan int=make(chan int,0)
    //ch<-1
    //ch<-2
    //ch<-3
    //ch<-4
    //fmt.Println(<-ch)
    //fmt.Println(<-ch)
    //fmt.Println(<-ch)

    //fmt.Println(<-ch) // 死锁

    // 2 信道的长度和容量:
    //长度目前信道中有多少值,容量是该信道能缓冲多少值
    // var ch chan int=make(chan int,3)
    // ch<-1
    // fmt.Println("长度是:",len(ch))
    // fmt.Println("容量是:",cap(ch))
    //
    //}


    func producer1(chnl chan int) {
    for i := 0; i < 10; i++ {
    chnl <- i

    }
    close(chnl)
    }
    func main() {
    ch := make(chan int,3)
    go producer1(ch)

    for v:=range ch{ // 通过range循环,如果信道没关闭,会一个个取值,如果信道关闭了,range之间结束

    fmt.Println("Received ", v)
    }
    }


     

    4.4 waitgroup

    package main

    import (
    "fmt"
    "sync"
    "time"
    )

    // 等待所有goroutine执行结束,主再执行
    // WaitGroup 方案


    func task5(i int,wg *sync.WaitGroup) {
    fmt.Println("我是任务", i)
    time.Sleep(1*time.Second)
    wg.Done() //一个任务结束,就调用一次done
    }

    func main() {
    var wg sync.WaitGroup // 值类型,不需要初始化,就有默认值
    for i := 0; i < 5; i++ {
    go task5(i,&wg)
    wg.Add(1) // 开始一个任务,就调用add
    }
    wg.Wait()
    fmt.Println("结束了")
    }

     

    5 select,mutex

    package main

    import (
    "fmt"
    "sync"
    "time"
    )

    // go中不推崇使用共享变量来共享数据,并发安全问题, 需要加锁
    // 推崇使用信道来共享数据
    var x = 0
    func increment(wg *sync.WaitGroup,lock *sync.Mutex) {
    lock.Lock()
    x = x + 1
    time.Sleep(1*time.Millisecond)
    lock.Unlock()

    wg.Done()
    }
    func main() {
    var w sync.WaitGroup
    var lock sync.Mutex
    for i := 0; i < 1000; i++ {
    w.Add(1)
    go increment(&w,&lock)

    }
    w.Wait()
    fmt.Println("final value of x", x)
    }
    package main

    import (
    "fmt"
    "time"
    )

    //select
    //func server1(ch chan string) {
    // time.Sleep(1 * time.Second)
    // ch <- "from server1"
    //}
    //func server2(ch chan string) {
    // time.Sleep(3 * time.Second)
    // ch <- "from server2"
    //
    //}
    //func main() {
    // output1 := make(chan string)
    // output2 := make(chan string)
    // go server1(output1)
    // go server2(output2)
    // select { // 从多个信道中选择最快的执行
    // case s1 := <-output1:
    // fmt.Println(s1)
    // case s2 := <-output2:
    // fmt.Println(s2)
    // }
    //}

    // 2 默认情况
    //func process(ch chan string) {
    // time.Sleep(10500 * time.Millisecond)
    // ch <- "process successful"
    //}
    //
    //func main() {
    // ch := make(chan string)
    // go process(ch)
    // for {
    // time.Sleep(1000 * time.Millisecond)
    // select {
    // case v := <-ch:
    // fmt.Println("received value: ", v)
    // return
    // default:
    // fmt.Println("no value received")
    // }
    // }
    //
    //}

    // 3 死锁问题
    //func main() {
    // ch := make(chan string)
    // select {
    // case <-ch:
    // }
    //}


    // 4 随机选取
    func server1(ch chan string) {
    ch <- "from server1"
    }
    func server2(ch chan string) {
    ch <- "from server2"

    }
    func main() {
    output1 := make(chan string)
    output2 := make(chan string)
    go server1(output1)
    go server2(output2)
    time.Sleep(1 * time.Second)
    select {
    case s1 := <-output1:
    fmt.Println(s1)
    case s2 := <-output2:
    fmt.Println(s2)
    }
    }

     

    6 异常处理

    package main

    import "fmt"

    // 异常处理:try except finally

    // panic,recover,defer

    // defer:延迟执行,先注册,后执行(整个函数执行完了,再按defer的注册顺序,从下网上执行),即便程序出现了严重错误,defer也会执行
    // panic: 就是python中的raise

    // recover:恢复程序,继续执行
    func main() {

    //defer fmt.Println("我最后执行")
    //defer fmt.Println("我倒数第二执行")
    //defer func() {
    // fmt.Println("我是一个匿名函数")
    //}()
    //fmt.Println("我先执行")

    //fmt.Println("我执行了")
    //panic("出错了")
    //fmt.Println("永远不会执行")


    //defer func() {
    // //recover()
    // fmt.Println("我恢复了")
    //}()
    //fmt.Println("我执行了")
    //panic("出错了")
    //fmt.Println("永远不会执行")



    //f1()
    //try:
    // f2()
    // f3()
    //except Exception as e:
    // print(e)


    //f1()
    //try:
    // f2()
    //except Exception as e:
    // print(e)
    // f3()

    f1()

    f2()

    f3()

    }

    func f1() {
    fmt.Println("我是f1")
    }
    func f2() {
    defer func() {
    if err:=recover();err!=nil{ // 如果不是nil表示有返回值,出异常了,处理异常
    fmt.Println(err)
    }
    //fmt.Println("用永远会执行,我就是finally的代码")
    }()
    fmt.Println("我是f2")
    panic("出错了我")
    //var a []int=[]int{1,2,3}
    //fmt.Println(a[99])
    }
    func f3() {
    fmt.Println("我是f3")
    }

    其他


    0 go操作mysql ,redis,es,kafka,rabbitmq
    1 go 的web框架
    -gin(类似于flask,借助于第三方,gorm框架),beego(类似于django:orm框架,缓存,信号。。。)

    2 微服务
    -go-zeor
       -go-micro
  • 相关阅读:
    上传文件 nginx 413错误
    javascript 获取指定范围随机数
    用CSS做圆角矩形
    CSS样式做圆角
    不用css样式表和背景图片实现圆角矩形,超简洁!
    HTML——框架
    HTML——表格与表单
    HTML构成及基本标签
    7-22 存储过程、触发器、事务
    15-07-20 数据库--索引视图编程
  • 原文地址:https://www.cnblogs.com/DEJAVU888/p/14894248.html
Copyright © 2011-2022 走看看