// 长度 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) }