zoukankan      html  css  js  c++  java
  • Go语法的基本使用(三)

    // 长度 vs 容量、
    // 长度是目前里面有几个值
    // 容量是最多能放多少个值
    func main(){
        var a =make(chan int,4)
            a<-1
            a<-2
            a<-5
            fmt.Println(len(a)) //3
            fmt.Println(cap(a))// 45
            <-a  // 取值
            fmt.Println(len(a))  // 2
            fmt.Println(cap(a)) // 4
    }

      一.协程

    package main
    
    import (
        "fmt"
        "time"
    )
    
    //go 协程
    
    func test()  {
        fmt.Println("hello go")
    }
    func main() {
        //goroutine
        go test()
        go test()
        go test()
        go test()
        go test()
        go test()
        go test()
        time.Sleep(time.Second*2)
    }

      二.值的存 和取

    package main
    
    import (
        "fmt"
        
    )
    
    // (2)信道 管道 通道
    
    // 信道也是个变量
    // 类型:信道运输的类型是int 类型
    // 性质:是一种引用的类型 所以需要在初始化的时候就得付初始值
    
    
    
    
    func task2(a chan bool) {
        fmt.Println("hello go ")
        // IO 一旦执行完毕,就往信道中放入一个值
    
        a <- true // 存值
        fmt.Println("666")
    }
    
    // 入口函数 理解
    
    func main(){
        // 必须初始化
        var a chan bool = make(chan bool)
        // 执行函数
        go task2(a)
        // 往里面存值
    
        // <- a// 取值
        x:=<-a
        fmt.Println(x)
    
    }

    ------------恢复内容结束------------

      一. 在方法中使用 值 接收器 与 在函数中使用 值 参数

      (1)定义用一个外部函数(接收器:接收值)方法中使用值接收器方法

    package main
    
    import "fmt"
    
    // 在方法中使用 值 接收器 与 在函数中使用 值 参数
    // 在方法中使用 指针 接收器 与函数再使用 指针 参数
    // 结构体
    type Person5 struct{
        name string
        age int
        sex int
    
    }
    
    // (1)定义用一个外部函数(接收器:接收值)方法中使用值接收器方法
    func (a Person5)printName(){
        fmt.Println(a.name)
        fmt.Println(a.age)
        fmt.Println(a.sex)
    
    
    }
    
    func main(){
        // 定义一个变量
        p:=Person5{name:"tt",age:18,sex:1}
        // 调用值接收器
        p.printName()

      (2)方法中使用指针接收器

    package main
    
    import "fmt"
    
    // 函数中使用 指针传值
    
    // (1)定义一个结构体
    type Person2 struct {
        name string
        age int
        sex int
    }
    
    // (2)定义一个函数 中功能代码
    func (a *Person2)printName(){
        // 需要执行的功能 哈
        fmt.Println(a.name)
        fmt.Println(a.age)
    }
    
    // (3)入口函数
    func main(){
        // 定义结构体的变量
        // var t *Person2=&Person2{name:"tt",age:18,sex:2}
        t:=&Person2{name:"tt",age:18,sex:2} // 值的传递可以省略类型
        t.printName()
    }

       

     (3)函数的值传递和指针传递        

      函数中使用值参数

    // (1)定义结构体
    type Person2 struct{
        name string
        age string
        sex int
        id int
    }
    
    // (2)定义一个外部功能函数 参数和结构体一一对应 其实还有返回值
    func printName(a Person2){
        fmt.Println(a.name)
        fmt.Println(a.age)
        fmt.Println(a.sex)
        fmt.Println(a.id)
    
    }
    
    // (3)入口函数 >>>> url 地址的入口
    
    func main()  {
        // (4)定义结构的变量的初始值
        //p:=Person2{}  //字符串则是 空 数字 则是0
        //fmt.Println(p,"---==")
         p:=Person2{name:"yy",age:"18",sex:2} // 不设置数字就是0
        printName(p)  // 函数就是传值 接收器(a Person) p点方法
    }

      

    (4)函数中的指针传递参数

    package main
    
    import "fmt"
    
    // (4)函数中的指针传递值
    
    // (1)go语言定义结构体
    type Person2 struct{
        name string
        age int
        sex int
        id int
    }
    
    // (2)外部执行功能函数
    
    func printName(a *Person2){
        fmt.Println(a.name)
        fmt.Println(a.age)
        fmt.Println(a.sex)
        fmt.Println(a.id)
    
    }
    
    // (3)入口函数
    func main(){
        // (4)定义变量及初始化
        p:=&Person2{age:18,name:"yuyu",sex:1,id:13} // 指名道姓 无关顺序
    
        printName(p) // &p和上面的一样获取地址
    
    }


      

      一.接收器如果不能进行识别需要进行重命名

    package main
    
    import "fmt"
    
    // 在非结构体上的方法 》》》重命名 接收器
    type MyInt int
    func (i *MyInt) add(){
        (*i)++
        fmt.Println(*i)  // 11
    
    }
    
    func main() {
        // 定义一个变量
        var a MyInt=10
        a.add()  // 接收器传值
        fmt.Println(a)  // 引用11
    
    }

      三,接口:是一系类方法的集合

      (1)实现方式一:接收器 传值  >>> mian 中点方法进行调用

    package main
    
    import "fmt"
    
    // 接口 继承 封装 多态  ,鸭子类型  重点*****
    // 接口:一系列方法的集合
    // (1)语法:
    // type 接口名 interface{
    //     test方法一()
    //     方法二功能()
    //      }
    
    // >>>(1)定义一个鸭子类的接口
    type Duck interface{
        run()
        speak()
    
    }
    
    // 结构体实现该接口(只要实现了接口中的所方法,该结构体实现了Duck接口)
    // >>>(2)定义一普通胖鸭子类 结构体
    type PDuck struct {
        // 属性
        name string
        age string
        id int
    
    }
    
    // (3)接口函数的值的传递
    func (p PDuck) run(){
        fmt.Println("我是第一只胖鸭子 会run")
    
    }
    
    func (p PDuck)speak(){
        fmt.Println("我是第一只胖鸭子 会speak")
    }
    
    
    // 定义一只唐老鸭 结构体
    type TDuck struct {
    
        name string
        age string
        wife bool
    }
    
    // 定义TDduct 的方法 不用函数实现
    func (p TDuck) run(){
        fmt.Println("我是唐老鸭 会run ")
        fmt.Println(p.name)
    }
    
    // 再定义一个speak  接收器方法
    
    func (p TDuck) speat(){
        fmt.Println("我是唐老鸭 会speak")
        fmt.Println(p.wife,"555") //
    
    }
    
    // (3)函数入口
    func main(){
        pD:=PDuck{name:"胖鸭子"}
        tD:=TDuck{name:"唐老鸭"}
        // 写一个函数:让鸭子说话,不管是唐老鸭还是胖鸭子
        pD.speak() // 我是第一只胖鸭子 会speak 可以调
        tD.speat() // 我是唐老鸭 会speak

      (2)实现接收器中函数的 run()  和speak() 方法  方法二:定义普通函数 在普通函数体内进行 run()  同时在我们的main中 调用 普通函数

    package main
    
    import "fmt"
    
    // 接口 继承 封装 多态  ,鸭子类型  重点*****
    // 接口:一系列方法的集合
    // (1)语法:
    // type 接口名 interface{
    //     test方法一()
    //     方法二功能()
    //      }
    
    // >>>(1)定义一个鸭子类的接口
    type Duck interface{
        run()
        speak()
    
    }
    
    // 结构体实现该接口(只要实现了接口中的所方法,该结构体实现了Duck接口)
    // >>>(2)定义一普通胖鸭子类 结构体
    type PDuck struct {
        // 属性
        name string
        age string
        id int
    
    }
    
    // (3)接口函数的值的传递
    func (p PDuck) run(){
        fmt.Println("我是第一只胖鸭子 会run")
    
    }
    
    func (p PDuck)speak(){
        fmt.Println("我是第一只胖鸭子 会speak")
    }
    
    
    // 定义一只唐老鸭 结构体
    type TDuck struct {
    
        name string
        age string
        wife bool
    }
    
    // 定义TDduct 的方法 不用函数实现
    func (p TDuck) run(){
        fmt.Println("我是唐老鸭 会run ")
        fmt.Println(p.name)
    }
    
    // 再定义一个speak  接收器方法
    
    func (p TDuck) speat(){
        fmt.Println("我是唐老鸭 会speak")
        fmt.Println(p.wife,"555") //
    
    }
    
    // (3)函数入口
    func main(){
        pD:=PDuck{name:"胖鸭子"}
        tD:=TDuck{name:"唐老鸭"}
        // 写一个函数:让鸭子说话,不管是唐老鸭还是胖鸭子
        //pD.speak() // 我是第一只胖鸭子 会speak 可以调
        //tD.speat() // 我是唐老鸭 会speak
        //// speak(tD,"yyyy") //接收器 不是函数 不能传值
        // 同时实现speak
        speak2(tD)  调用普通函数
        speak(pD)
        // XXX(pD)
        var d Duck
        d=pD
        // d=tD
        fmt.Println(d,"xxxx")  // {唐老鸭  false} xxxx
    
    
    }
    // (4)函数 的传值
    func speak(p PDuck){
        p.speak()   调用接收器中的方法
    }
    
    func speak2(p TDuck){
        p.speat()
    }
    
    func XXX(p PDuck){
        p.run()  // 在一个函数调用另一个函数
        fmt.Println(p.name) 调用接收器的方法
    }

      四、断言 switch 判断子类的属性和方法

    package main
    
    import "fmt"
    
    // 接口 继承 封装 多态  ,鸭子类型  重点*****
    // 接口:一系列方法的集合
    // (1)语法:
    // type 接口名 interface{
    //     test方法一()
    //     方法二功能()
    //      }
    
    // >>>(1)定义一个鸭子类的接口
    type Duck interface{
        run()
        speak()
    
    }
    
    // 结构体实现该接口(只要实现了接口中的所方法,该结构体实现了Duck接口)
    // >>>(2)定义一普通胖鸭子类 结构体
    type PDuck struct {
        // 属性
        name string
        age string
        id int
    
    }
    
    // (3)接口函数的值的传递
    func (p PDuck) run(){
        fmt.Println("我是第一只胖鸭子 会run")
    
    }
    
    func (p PDuck)speak(){
        fmt.Println("我是第一只胖鸭子 会speak")
    }
    
    
    // 定义一只唐老鸭 结构体
    type TDuck struct {
    
        name string
        age string
        wife bool
    }
    
    // 定义TDduct 的方法 不用函数实现
    func (p TDuck) run(){
        fmt.Println("我是唐老鸭 会run ")
        fmt.Println(p.name)
    }
    
    // 再定义一个speak  接收器方法
    
    func (p TDuck) speat(){
        fmt.Println("我是唐老鸭 会speak")
        fmt.Println(p.wife,"555") //
    
    }
    
    // (3)函数入口
    func main(){
        pD:=PDuck{name:"胖鸭子"}
        tD:=TDuck{name:"唐老鸭"}
        // 写一个函数:让鸭子说话,不管是唐老鸭还是胖鸭子
        //pD.speak() // 我是第一只胖鸭子 会speak 可以调
        //tD.speat() // 我是唐老鸭 会speak
        //// speak(tD,"yyyy") //接收器 不是函数 不能传值
        // 同时实现speak
        speak2(tD)  调用普通函数
        speak(pD)
        // XXX(pD)
        var d Duck
        d=pD
        // d=tD
        fmt.Println(d,"xxxx")  // {唐老鸭  false} xxxx
    
    
    }
    // (4)函数 的传值
    func speak(p PDuck){
        p.speak()   调用接收器中的方法
    }
    
    func speak2(p TDuck){
        p.speat()
    }
    
    func XXX(p PDuck){
        p.run()  // 在一个函数调用另一个函数
        fmt.Println(p.name) 调用接收器的方法
    }

     截图suoshi:

      空接口

    package main
    
    import "fmt"
    
    // 空接口(一个方法都没有)
    // 匿名空接口
    // 所有的数据类型都实现了空接口
    // 类似于一个父类
    type Empty interface{
    
    }
    
    type TDuck2 struct {
        name string
        age int
        wife bool
    
    }
    
    // 入口函数
    func main(){
        test3(1)
        test3("sss")
        test3(TDuck2{})
        test3(10.233432423)
    
        //var a Empty=1
        //var b Empty="IOOIO"
    }
    
    //func test(a Empty){
    //    fmt.Println(a)
    //}
    
    func test3(a interface{})  {
        switch a.(type) {
        case int:
            fmt.Println("int类型")
        case string:
            fmt.Println("string")
        case TDuck2:
            fmt.Println("老鸭子")
        default:
            fmt.Println("啥类型")
        }

      五.异常处理

    package main
    
    import (
        "fmt"
    
    )
    
    // 异常处理
    // defer  延迟调用 即便程序出现严重错误 也会执行
    // panic 就是python中的raise(主动跑出异常)
    // recover 恢复程序, 继续执行
    
    func main() {
        //先注册,后调用
        //defere ????
        fmt.Println("xxx")
        //  defere
        fmt.Println("yyyy")
        //f1()  // 调用
        f2()  // 调用
        //f3()  // 调用
    }
    
    func f1(){
        fmt.Println("f1...")
    
    }
    
    
    func f2(){
        defer func() {
            if a:=recover();a!=nil{
                // a 如果不等于nil, 表示程序出了异常, a就是异常信息
                // a 等于nil 表示没有异常
                fmt.Println("代码异常出错;了")
            }//用于会被执行(相当于finally)
    
        }()  // 这里执行函数
        fmt.Println("f2...")
        // var a = make([]int,3,3)
        // fmt.Println(a[4])
        panic("主动抛异常")
    }
    func f3(){
        fmt.Println("f3...")
    }

      六。自定义set       map 去重

    package main
    
    import "fmt"
    
    // (1)自定义set() 可以放值
    
    
    type MySet map[interface{}]bool
    //func (s MySet)isExist(a interface{}) bool {
    //    return s[a]  // 这只是个接口 判断
    //}
    
    // 定义接口函数 interface{} 其实大可不必要用*号
    func (s *MySet) set(a interface{}){
        (*s)[a]=true  //
    }
    
    //用函数 就是一个普通的接收器函数// 可以查看长度
    func (s MySet)len()int {
        return len(s)
    }
    
    // // 可以打印所有内容 MySet 》》》 类接收器
    func (a MySet)printAll(){
        for k,v:=range a{// 关键字range + s 变量
            fmt.Println(k,v,"000--")
        }
    }
    
    
    func main()  {
    
        //   MySet = map[interface{}]bool 这个类型
        var a MySet=make(MySet)
        fmt.Println(a) // 空类型map[]
        a.set("1")
        a.set("1")
        a.set("2")
        fmt.Println(len(a))
        fmt.Println(a)
        fmt.Println(a.len())
        a.printAll()
    
    }

      七.信道

      (1)只写信道

    package main
    
    import "fmt"
    
    // 单向信道只能放或 取 chan 关键字 a:=<-b 取    a<- 存取 箭头
    func sendData(sendch chan<-int){
        sendch<-10
    }
    
    func main(){
        //只写信道
        sendch :=make(chan int)
        go sendData(sendch)
        fmt.Println(<-sendch)
    }

      (信道死锁的问题)

    package main
    
    import "fmt"
    
    // 单向信道只能放或 取
    //func sendData(sendch chan<-int){
    //    sendch<-10
    //}
    //
    //func main(){
    //    //只写信道
    //    sendch :=make(chan int)
    //    go sendData(sendch)
    //    fmt.Println(<-sendch)
    //}
    
    // 关闭信道和使用 for range 遍历信道
    
    func task3(ccc chan int){
        for i:=0;i<10;i++{
            ccc<-i
        }
        close(ccc) // 关闭即可
    }
    
    func main(){
        // 类型定义
        c:=make(chan int)
        go task3(c)
        // 死循环在监听我们的事件
        for {
            v,ok:=<-c
            // 如果信道关闭,OK就是false
            if ok==false{
                break
            }
            fmt.Println("打印",v,ok)
        }
    
        }
    
    // 出现死锁:fatal error: all goroutines are asleep - deadlock!
    // 在for 循环结束后关闭存储任务 即可 解决死锁问题

      2.信道缓存  》》》 设定缓存大小

     (1)

    package main
    
    import "fmt"
    
    // 信道缓冲
    func main(){
        // 初始化
        var t chan int=make(chan int,1) // 0 前期缓存值
        t<-1 // 将1 存入a 信道中 不写默认为0 根本存不进去
        b:=<-t
        fmt.Println("xxx",b)
    }

      (2)容量

    package main
    
    import (
        "fmt"
        "time"
    )
    
    // 列子
    
    func write(ddd chan int){
        // ddd 就相当于一个容器
        for i:=0;i<10;i++{
            ddd<-i
    
        }
        close(ddd)
    
    }
    
    // 入口函数
    func main()  {
        // 初始定义类型和信道类型 和 容量
        var ddd chan int=make(chan int,5)
        go write(ddd)
        // 做io
        time.Sleep(2*time.Second)
        for v:=range ddd{
            fmt.Println("reader value",v,"from ddd")
            time.Sleep(2*time.Second)
        }
    
    }

      (3)容量和长度

    // 长度 vs 容量、
    // 长度是目前里面有几个值
    // 容量是最多能放多少个值
    func main(){
        var a =make(chan int,4)
            a<-1
            a<-2
            a<-5
            fmt.Println(len(a)) //3
            fmt.Println(cap(a))// 45
            <-a  // 取值
            fmt.Println(len(a))  // 2
            fmt.Println(cap(a)) // 4
    }

       (4)sync.WaitGroup 

    package main
    
    import (
        "fmt"
        "sync"
        "time"
    )
    
    // waitgroup:等待所有go协程执行完成
    func task4(wg *sync.WaitGroup,i int){
        time.Sleep(time.Second*2)
        fmt.Println(i)
        wg.Done()  //
    }
    
    func main(){
        // sync包下的waitGroup,是个值类型,当参传递,需要地址
        var wg sync.WaitGroup  // 定义
        for i:=0;i<5;i++ {
            //wg.Add表示标志了起了一个goroutine
            wg.Add(1)
            go task4(&wg, i)
        }
        // 等待所有协程执行完成
        wg.Wait()
        fmt.Println("都执行完了")
    }

      (5)通过信道实现

    //package main
    //
    //import (
    //"fmt"
    //"sync"
    //"time"
    //)
    //
    //// waitgroup:等待所有go协程执行完成
    //func task4(wg *sync.WaitGroup,i int){
    //    time.Sleep(time.Second*2)
    //    fmt.Println(i)
    //    wg.Done()  //
    //}
    //
    //func main(){
    //    // sync包下的waitGroup,是个值类型,当参传递,需要地址
    //    var wg sync.WaitGroup  // 定义
    //    for i:=0;i<5;i++ {
    //        //wg.Add表示标志了起了一个goroutine
    //        wg.Add(1)
    //        go task4(&wg, i)
    //    }
    //    // 等待所有协程执行完成
    //    wg.Wait()
    //    fmt.Println("都执行完了")
    //
    //}
    package main
    
    import (
        "fmt"
        "time"
    )
    
    // 通过信道实现
    func main(){
        var a =make(chan bool)
        for i:=0;i<5;i++{
            go task6(a,i) // 将信道和i 值传送到我们的函数中
        }
        for i:=0;i<5;i++{
            <-a // 取值
        }
        fmt.Println("都执行完了")
    }
    // 传值传几个接收几个 以及类型
    
    func task6(a chan bool,i int){
        time.Sleep(time.Second*2)
        fmt.Println(i)
        a<-true  // 将值存入我们a 信道中
    
    }

      七。中的锁

    package main
    
    import (
        "fmt"
        "sync"
    )
    
    // go 中的锁实现数据的安全
    
    // 功能
    var x=0
    func incrament(wg *sync.WaitGroup,m *sync.Mutex){
        // 布置锁
        m.Lock()
        x = x+10
        m.Unlock()
        wg.Done()
        fmt.Println(x)  // 从10开始
    
    }
    
    
    func main(){
        var w sync.WaitGroup // 定义变量
        var m sync.Mutex // 定义锁  // 值类型 ,传递地址
        for i:=0;i<1000;i++{
            w.Add(1)
            go incrament(&w,&m)
            
        }
        w.Wait()
        fmt.Println("都执行完毕了",x)  // 拿到最后的值
    }

      (2)信道也是保证数据安全?

    //package main
    //
    //import (
    //    "fmt"
    //    "sync"
    //)
    //
    //// go 中的锁实现数据的安全
    //
    //// 功能
    //var x=0
    //func incrament(wg *sync.WaitGroup,m *sync.Mutex){
    //    // 布置锁
    //    m.Lock()
    //    x = x+10
    //    m.Unlock()
    //    wg.Done()
    //    fmt.Println(x)  // 从10开始
    //
    //}
    //
    //
    //func main(){
    //    var w sync.WaitGroup // 定义变量
    //    var m sync.Mutex // 定义锁  // 值类型 ,传递地址
    //    for i:=0;i<1000;i++{
    //        w.Add(1)
    //        go incrament(&w,&m)
    //
    //    }
    //    w.Wait()
    //    fmt.Println("都执行完毕了",x)  // 拿到最后的值
    //}
    
    // 通过信到实现数据的存值
    package main
    
    import (
        "fmt"
        "sync"
    )
    var x=0
    func increment(w *sync.WaitGroup,ch chan bool){
        ch<-true // 进行存储
        x=x+10
        <-ch
        w.Done() // 执行
        fmt.Println(x,"执行x")
    }
    
    
    
    func main(){
        var w sync.WaitGroup // 定义一个
        ch :=make(chan bool,1)
        for i:=0;i<5;i++{
            w.Add(1)
            go increment(&w,ch)
    
        }
        w.Wait()
        fmt.Println("final value ofx",x)
    
    }
  • 相关阅读:
    【leetcode】反转字符串
    【leetcode】反转字符串 II
    053-669
    053-668
    053-667
    053-666
    053-665
    053-664
    053-663
    053-662
  • 原文地址:https://www.cnblogs.com/mofujin/p/12037313.html
Copyright © 2011-2022 走看看