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)

}
posted @ 2019-12-14 00:24  可乐'不加冰  阅读(455)  评论(0编辑  收藏  举报