272_尚硅谷_管道的细节和课堂练习

1.channel 使用的注意事项1.channel 使用的注意事项

2.如果从 channel 取出数据后, 可以继续放入2.如果从 channel 取出数据后, 可以继续放入

package main

import (
	"fmt"
)

// todo 演示管道的使用
func main() {
	// 1. 创建一个可以存放3个int类型的管道
	var intChan chan int
	intChan = make(chan int, 3)
	// 2. 看看intChan是什么
	fmt.Printf("intChan 的值= %v intChan 本身的地址= %p\n", intChan, &intChan)

	// 3. 向管道写入数据
	intChan <- 10
	intChan <- 20
	intChan <- 30
	// ! 如果从 channel 取出数据后, 可以继续放入
	<-intChan // * 解释: 从intChan 取出数据不用了,理解为删除, 可以不赋值
	// ! 注意点:当我们向管道写入数据时(案例是3个int),不能超过其容量, 但是可以边写入边读取
	intChan <- 40

	// 4. 看看管道的长度和容量(cap)
	fmt.Println("=============== 4.看看管道的长度和容量(cap) ================")
	fmt.Printf("len(intChan)= %v cap(intChan)= %v\n", len(intChan), cap(intChan))

	// 5. 从管道读取数据
	var num2 int
	num2 = <-intChan // ! 注意点:当我们从管道读取数据时,如果管道中没有数据,就会阻塞等待
	fmt.Println("=============== 5. 读取管道数据 ================")
	fmt.Println("num2=", num2)

	// 6. 取完数据后, 再看管道的长度和容量(cap)
	fmt.Println("=============== 6. 取完数据后, 再看管道的长度和容量(cap) ================")
	fmt.Printf("len(intChan)= %v cap(intChan)= %v\n", len(intChan), cap(intChan))

	// 7. 在没有使用协程的情况下,如果管道数据全部取出,再取就会报错 deadlock
	fmt.Println("=============== 7. 在没有使用协程的情况下,如果管道数据全部取出,再取就会报错 deadlock ================")
	num3 := <-intChan
	num4 := <-intChan
	fmt.Println("num3=", num3, "num4=", num4)

}

3.如果从 channel 取出数据后, 可以继续放入_运行结果3.如果从 channel 取出数据后, 可以继续放入_运行结果

4.1) 创建一个intChan,最多可以放3个int, 演示存3数据到intChan, 然后再取出这三个int4.1) 创建一个intChan,最多可以放3个int, 演示存3数据到intChan, 然后再取出这三个int

package main

import (
	"fmt"
)

// todo 1) 创建一个intChan,最多可以放3个int, 演示存3数据到intChan, 然后再取出这三个int
func main() {
	// 1. 创建一个可以存放3个int类型的管道
	var intChan chan int
	intChan = make(chan int, 3)
	// 2. 看看intChan是什么
	fmt.Printf("intChan 的值= %v intChan 本身的地址= %p\n", intChan, &intChan)

	// 3. 向管道写入数据
	intChan <- 10
	intChan <- 20
	intChan <- 30

	// 4. 取值
	num1 := <-intChan
	num2 := <-intChan
	num3 := <-intChan

	fmt.Printf("===============  1) 创建一个intChan, 最多可以放3个int, 演示存3数据到intChan, 然后再取出这三个int ===============\n")
	fmt.Printf("num1= %v, num2= %v, num3= %v", num1, num2, num3)

}

5.2) 创建一个mapChan, 最多可以存放10个map[string]string 的key-val, 演示写出和写入5.2) 创建一个mapChan, 最多可以存放10个map[string]string 的key-val, 演示写出和写入

package main

import "fmt"

// todo 2) 创建一个mapChan, 最多可以存放10个map[string]string 的key-val, 演示写出和写入
func main() {
	// 1) 创建一个mapChan,最多可以存放10个map[string]string
	var mapChan chan map[string]string
	// 2) 创建map并写入数据
	mapChan = make(chan map[string]string, 10)
	m1 := make(map[string]string, 20)
	m1["city1"] = "北京"
	m1["city2"] = "天津"
	m2 := make(map[string]string, 20)
	m2["hero1"] = "宋江"
	m2["hero2"] = "武松"

	mapChan <- m1
	mapChan <- m2

	// 使用for循环读取所有数据
	// 注意: 需要重新创建管道,因为上面的代码已经读完了
	fmt.Println("使用for循环读取:")
	mapChan2 := make(chan map[string]string, 10)
	mapChan2 <- m1
	mapChan2 <- m2
	// ! 关闭管道后可以使用range遍历
	close(mapChan2)

	// ! 注意:for range遍历管道(channel)的正确语法: for item := range channel {}
	for m := range mapChan2 {
		fmt.Println(m)
	}
}

6.3) 创建一个catChan, 最多可以存放10个Cat结构体变量, 演示写入和读取的用法6.3) 创建一个catChan, 最多可以存放10个Cat结构体变量, 演示写入和读取的用法

package main

import "fmt"

type Cat struct {
	Name string
	Age  int
}

// todo 3) 创建一个catChan, 最多可以存放10个Cat结构体变量, 演示写入和读取的用法
func main() {
	// 1) 创建一个catChan, 最多可以存放10个Cat结构体变量
	var catChan chan Cat
	catChan = make(chan Cat, 10)
	// 创建cat结构体
	cat1 := Cat{Name: "tom1", Age: 18}
	cat2 := Cat{Name: "tom2", Age: 20}
	catChan <- cat1
	catChan <- cat2

	// 取出结构体内容
	cat1_con := <-catChan
	cat2_con := <-catChan

	fmt.Printf("cat1_con= %v, cat2_con= %v", cat1_con, cat2_con)

}

7.4) 创建一个catChan2, 最多可以存放 10个Cat变量, 演示写入和读取的用法7.4) 创建一个catChan2, 最多可以存放 10个Cat变量, 演示写入和读取的用法

package main

import "fmt"

type Cat struct {
	Name string
	Age  int
}

// todo 4) 创建一个catChan2, 最多可以存放 10个*Cat变量, 演示写入和读取的用法
func main() {
	// 1) 创建一个catChan2, 最多可以存放 10个*Cat变量
	var catChan chan *Cat
	catChan = make(chan *Cat, 10)
	// 创建cat结构体
	cat1 := Cat{Name: "tom1", Age: 18}
	cat2 := Cat{Name: "tom2", Age: 20}
	catChan <- &cat1
	catChan <- &cat2

	// 关闭通道(可选,但在读取完后关闭是好习惯)
	close(catChan)

	// 取出结构体内容
	catFromChan1 := <-catChan
	catFromChan2 := <-catChan

	fmt.Printf("catFromChan1= %v, catFromChan2= %v", catFromChan1, catFromChan2)
}

8.5) 创建一个 allChan, 最多可以存放 10个 任意数据类型变量, 演示写入和读取的用法8.5) 创建一个 allChan, 最多可以存放 10个 任意数据类型变量, 演示写入和读取的用法

 

package main

import "fmt"

type Cat struct {
	Name string
	Age  int
}

// todo 5) 创建一个 allChan, 最多可以存放 10个 任意数据类型变量, 演示写入和读取的用法
func main() {
	// 5) 创建一个 allChan, 最多可以存放 10个 任意数据类型变量
	var allChan chan interface{} // ! 定义空接口
	allChan = make(chan interface{}, 10)

	// 创建cat结构体
	cat1 := Cat{Name: "tom1", Age: 18}
	cat2 := Cat{Name: "tom2", Age: 20}
	// 给空接口类型填写数据
	allChan <- cat1
	allChan <- cat2
	allChan <- 10
	allChan <- "jack"

	// 取出
	allChancat1 := <-allChan
	allChancat2 := <-allChan
	v1 := <-allChan
	v2 := <-allChan
	fmt.Println("=============== 5) 创建一个 allChan, 最多可以存放 10个 任意数据类型变量, 演示写入和读取的用法 ===============")
	fmt.Printf("allChancat1= %v, allChancat2= %v, v1= %v, v2= %v", allChancat1, allChancat2, v1, v2)

}

 

9.6) 查看代码输出内容9.6) 查看代码输出内容

 

package main

import "fmt"

type Cat struct {
	Name string
	Age  int
}

// todo 6) 查看代码输出内容
func main() {
	//  6) 查看代码输出内容
	var allChan chan interface{} // ! 定义空接口
	allChan = make(chan interface{}, 10)

	// 创建cat结构体
	cat1 := Cat{Name: "tom1", Age: 18}
	cat2 := Cat{Name: "tom2", Age: 20}
	// 给空接口类型填写数据
	allChan <- cat1
	allChan <- cat2
	allChan <- 10
	allChan <- "jack"

	// 取数据,
	cat11 := <-allChan
	fmt.Printf("cat11 type= %T, con= %v", cat11, cat11)
	fmt.Println(cat11.Name) // ! 报错: cat11.Name undefined (type interface{} has no field or method Name)
}

 

10.使用类型断言,取出接口中结构体下指定字段的内容

10.使用类型断言,取出接口中结构体下指定字段的内容

package main

import "fmt"

type Cat struct {
	Name string
	Age  int
}

func main() {
	// 定义一个存放任意数据类型的管道 3个数据
	allChan := make(chan interface{}, 3)

	allChan <- 10
	allChan <- "tom jack"
	cat := Cat{"cat1", 4}

	allChan <- cat

	// 希望单独获得管道中第3个元素,则先将前两个推出
	<-allChan
	<-allChan

	newCat := <-allChan // ! 注: 如果直接newCat.Name会报错, newCat是一个接口类型, 不能直接取字段内容
	fmt.Printf("newCat_type= %T, newCat= %v\n", newCat, newCat)
	fmt.Printf("=============== 注: 如果直接newCat.Name会报错, newCat是一个接口类型, 不能直接取字段内容, 编译不通过 ===============\n")
	// fmt.Printf("newCat.Name= %v", newCat.Name)

	// ! 使用类型断言后, 类型不改变, 结构体可以取出单独字段内容
	a := newCat.(Cat)
	fmt.Printf("=============== 使用类型断言, 类型不改变, 结构体可以取出单独字段内容 ===============\n")
	fmt.Printf("a type= %T, a.Name= %v", a, a.Name)
}

posted on 2026-03-04 16:08  与太阳肩并肩  阅读(1)  评论(0)    收藏  举报

导航