(1)channel本质就是一个数据结构——队列
(2)数据先进先出
(3)线程安全,多goroutine访问时,不需要加锁,channel本身就是线程安全的
(4)channel是有类型的,一个int类型的channel只能存放int类型的数据
(5)定义声明chan:
var chan_name chan 变量类型
package main
import (
"fmt"
)
func main() {
// 创建一个可以存放3个int类型的管道
var intChan chan int
intChan = make(chan int, 3)
// 打印intChan
fmt.Printf("intChan的值 = %v intChan本身的地址 = %p\n", intChan, &intChan)
// 向管道写入数据,当我们向管道写入数据时,不可以超过其容量
intChan <- 10
num := 100
intChan <- num
// 管道的长度和cap(容量)
fmt.Printf("intChan len = %v cap=%v\n", len(intChan), cap(intChan))
// 从管道中读取数据
var num2 int
num2 = <- intChan
fmt.Println("num2 =", num2)
// 管道的长度和cap(容量)
fmt.Printf("intChan len = %v cap=%v\n", len(intChan), cap(intChan))
// 在没有使用协程的情况下,如果我们的管道数据已经全部取出,再取就会报告deadlock
}
package main
import (
_"fmt"
)
func main() {
var mapChan chan map[string]string
mapChan = make(chan map[string]string, 10)
m1 := make(map[string]string, 20)
m1["city1"] = "New York"
m1["city2"] = "Washington DC"
m2 := make(map[string]string, 20)
m2["name1"] = "Sophia"
m2["name2"] = "Maria"
mapChan <- m1
mapChan <- m2
}
package main
import (
"fmt"
)
type Cat struct{
Name string
Age int
}
func main() {
var catChan chan Cat
catChan = make(chan Cat, 10)
cat1 := Cat{Name:"Tom", Age:3,}
cat2 := Cat{Name:"Jack", Age:4,}
catChan <- cat1
catChan <- cat2
cat11 := <- catChan
cat22 := <- catChan
fmt.Println(cat11, cat22)
fmt.Println(cat11.Name)
}
package main
import (
"fmt"
)
type Cat struct{
Name string
Age int
}
func main() {
var catChan chan *Cat
catChan = make(chan *Cat, 10)
cat1 := Cat{Name:"Tom", Age:3,}
cat2 := Cat{Name:"Jack", Age:4,}
catChan <- &cat1
catChan <- &cat2
cat11 := <- catChan
cat22 := <- catChan
fmt.Println(cat11, cat22)
fmt.Println(cat11.Name)
}
package main
import (
"fmt"
)
type Cat struct{
Name string
Age int
}
func main() {
// 定义一个存放任意数据类型的管道,3个数据
// var allChan chan interface{}
// allChan = make(chan interface{}, 3)
allChan := make(chan interface{}, 3)
allChan <- 10
allChan <- "tom"
cat := Cat{"blossom", 4}
allChan <- cat
// 获取管道中第三个元素
<- allChan
<- allChan
newCat := <-allChan
fmt.Printf("newCat = %T, newCat = %v\n", newCat, newCat)
// ./go_t.go:31:41: newCat.Name undefined (type interface {} is interface with no methods)
// fmt.Printf("newCat.Name = %v\n", newCat.Name)
// 正确方法,使用类型断言
a := newCat.(Cat)
fmt.Printf("newCat.Name = %v\n", a.Name)
}
(1)channel的关闭
(2)channel的遍历
(3)channel的关闭和遍历示例:
package main
import (
"fmt"
)
func main() {
intChan := make(chan int, 3)
intChan <- 100
intChan <- 200
// close
close(intChan)
fmt.Println("ok")
// 管道关闭后是可以读取数据的
n1 :=<- intChan
fmt.Println("n1 =", n1)
// 遍历
intChan2 := make(chan int, 100)
for i := 0; i < 100; i++ {
// 放入100个数据到intChan2
intChan2 <- i * 2
}
// 这种遍历方式只能取出50个数字,因为每取出一个数字,len(intChan2)就减一
// for i := 0; i < len(intChan2); i++ {
// }
close(intChan2)
// for-range取值没有下标不需要 _, v := range intChan2
for v := range intChan2 {
// 如果管道没有关闭,那么数据是可以全部取出来的,但是会有错误:fatal error: all goroutines are asleep - deadlock!
fmt.Println("v =", v)
}
}
Go资料大全:https://github.com/0voice/Introduction-to-Golang
Go中文网链接:https://studygolang.com/
Golang标准文档:https://studygolang.com/pkgdoc
原文:https://www.cnblogs.com/vivianwenwen/p/15156456.html