Go 语言从入门到实战
蔡超
Mobvista 技术副总裁兼首席架构师,前亚马逊(中国)首席软件架构师
48919 人已学习
新⼈⾸单¥59
课程目录
已完结/共 55 讲
第一章:Go语言简介 (4讲)
第二章:基本程序结构 (4讲)
第三章:常用集合 (3讲)
第四章:字符串 (1讲)
时长 16:47
第五章:函数 (2讲)
第六章:面向对象编程 (4讲)
第七章:编写好的错误处理 (2讲)
第八章:包和依赖管理 (2讲)
第九章:并发编程 (7讲)
第十章:典型并发任务 (5讲)
第十一章:测试 (3讲)
时长 11:48
时长 07:12
时长 06:15
第十二章:反射和Unsafe (3讲)
时长 08:18
时长 08:03
第十三章:常见架构模式的实现 (2讲)
第十四章:常见任务 (4讲)
时长 04:27
时长 05:14
第十五章:性能调优 (4讲)
第十六章:高可用性服务设计 (5讲)
Go 语言从入门到实战
登录|注册
留言
11
收藏
沉浸
阅读
分享
手机端
回顶部
当前播放: 32 | 所有任务完成
00:00 / 00:00
高清
  • 高清
1.0x
  • 2.0x
  • 1.5x
  • 1.25x
  • 1.0x
  • 0.75x
  • 0.5x
网页全屏
全屏
00:00
付费课程,可试看
01 | Go语言课程介绍
02 | 内容综述
03 | Go语言简介:历史背景、发展现状及语言特性
04 | 编写第一个Go程序
05 | 变量、常量以及与其他语言的差异
06 | 数据类型
07 | 运算符
08 | 条件和循环
09 | 数组和切片
10 | Map声明、元素访问及遍历
11 | Map与工厂模式,在Go语言中实现Set
12 | 字符串
13 | Go语言的函数
14 | 可变参数和defer
15 | 行为的定义和实现
16 | Go语言的相关接口
17 | 扩展与复用
18 | 不一样的接口类型,一样的多态
19 | 编写好的错误处理
20 | panic和recover
21 | 构建可复用的模块(包)
22 | 依赖管理
23 | 协程机制
24 | 共享内存并发机制
25 | CSP并发机制
26 | 多路选择和超时
27 | channel的关闭和广播
28 | 任务的取消
29 | Context与任务取消
30 | 只运行一次
31 | 仅需任意任务完成
32 | 所有任务完成
33 | 对象池
34 | sync.pool对象缓存
35 | 单元测试
36 | Benchmark
37 | BDD
38 | 反射编程
39 | 万能程序
40 | 不安全编程
41 | 实现pipe-filter framework
42 | 实现micro-kernel framework
43 | 内置JSON解析
44 | easyjson
45 | HTTP服务
46 | 构建RESTful服务
47 | 性能分析工具
48 | 性能调优示例
49 | 别让性能被锁住
50 | GC友好的代码
51 | 高效字符串连接
52 | 面向错误的设计
53 | 面向恢复的设计
54 | Chaos Engineering
55 | 结课测试&结束语
登录 后留言

全部留言(11)

  • 最新
  • 精选
「ZY」
蔡老师您好: 您这节课的代码 有没有可能会出现 channel在取数的时候,上面的go协程还没跑完 ch里面还没有数据 for i:0;i<10;i++{ go func(){ ch<-ret } } total="" for i:0;i<10;i++{ total+=<-ch }

作者回复: 主携程会阻塞等待接收10个ch传来的我数据。所以在循环退出前程序不会退出

2019-03-26
3
橙子
for i:=1;i<=10;i++{ go func(){ ch<-ret } } for i:=1;i<=10;i++{ <-ch } 老师 针对以上程序我有个疑问,怎样可以使用 for range 而不用以上的 for 递增循环,因为看到网上 有for range 遍历 channel for v:=range ch { fmt.Println(v) } 其实我想问的是 这种情况下 在哪里close后 再进行for range 希望老师帮忙解答

作者回复: 继续看我的close和广播那一节,你就会有答案

2019-04-01
2
2
escray
从示例代码来看,与上一节相比,仅仅只是多了一个聚合操作,将所有协程的操作,ch <- ret,从 channel 中取出来,+= <-ch,然后再 return。 如果和 WaitGroup 的方式来比较的话,不知道各自有什么优劣?

作者回复: 其实是两种不同的编程模型,在前面有过介绍

2021-04-10
1
manatee
想请教下老师学习go的话哪些书籍或者学习资料比较有用呢

作者回复: 最有用的就是那本经典“Go programming”和Go的官方文档了。另外,youtube上有不少Go创始人的视频讲座都值得看看。

2019-04-03
1
Geek_4c7e99
老师 我按照这个代码发现每次打印出来每次开启的协程数目都不一致,是与我的硬件机器有关系吗

作者回复: Before和After的一样吗? 什么机器?

2019-08-01
2
Clany
老师,我往channel里面放的生产的数量,比如初始化i:=5,然后消费哪里还是j:=0,生产的不够消费就会阻塞,出现死锁情况。channel信道的输入输出一般是 成对 出现的,如果不成对那边就会出现死锁的情况。但是我如果反过来,生产大于消费,它不会阻塞,这种情况怎么理解呢? func AllResponse() string { numOfRunner := 10 ch := make(chan string, numOfRunner) for i := 5; i < numOfRunner; i++ { go func(i int) { ret := runTask(i) ch <- ret }(i) } finalRet := "" for j := 0; j < numOfRunner; j++ { finalRet += <-ch + "\n" } return finalRet } 报错:fatal error: all goroutines are asleep - deadlock!

作者回复: 当你的buffered chan满的时候生产者放不进东西一样阻塞,但是你要注意你的接受者是主协程,而你的生产者是其他协程,所以不管生产者协程是否被阻塞,主要外部主协程退出,就会整合都推出了

2019-04-08
NIXUS
老师, 我又去看了close和广播的那节课, 然后改了下代码, 但是这个并不是安全的, 偶尔会有致命错误(fatal error: all goroutines are asleep - deadlock!), 希望老师能够指点一下, 是哪里需要调整, 谢谢您了! 麻烦您指点一下 var wg sync.WaitGroup func AllResponse() string { numOfRunner := 10 ch := make(chan string, numOfRunner) for i := 0; i < 10; i++ { go func(i int) { wg.Add(1) ch <- runTask(i) }(i) } finalStr := "" // for i := 0; i < numOfRunner; i++ { // finalStr += <-ch + "\n" // } go func() { for { if v, ok := <-ch; ok { fmt.Println(v, ok) finalStr += v + "\n" } else { break } } wg.Done() }() wg.Wait() return finalStr } func TestAllResponse(t *testing.T) { fmt.Print(AllResponse()) time.Sleep(time.Second) }

作者回复: 1. 你的wg.Add(1)要放在子线程的外面。你可以再仔细看看课程里的代码。 2. 实际上你没有必要用wait group,利用chan的阻塞就不会推出,只有channel关闭时才会break循环 3. 代码里没看见close啊

2019-04-02
2
八宝
方案1 golang的 CSP模型(独有),goroutine + channel; 方案2 sync.WaitGroup, 和Java的 CountDonwLatch 类似。 补充方案2 sync.WaitGroup代码 func RunTask(i int) string { time.Sleep(time.Millisecond * 10) return fmt.Sprintf("return form %d", i) } func TestWaitAllResponseDone(t *testing.T) { numOfRunner := 10 var wg sync.WaitGroup strSlice := make([]string, numOfRunner) //这里 length 和 capacity 都是 10,接收返回值 for i := 0; i < numOfRunner; i++ { wg.Add(1) go func(i int) { strSlice[i] = RunTask(i) //通过i 保证每个协程修改的地方独立,thread-safe wg.Done() }(i) } wg.Wait() fmt.Println("all result:\n", strings.Join(strSlice, ",\n")) // 使用 12讲 strings的Join函数 fmt.Print(len(strSlice), cap(strSlice)) //验证 切片的长度和容量 }
2021-03-05
3
郭星
// 实现所有任务返回且关闭channel func AllResponse() string { numOfRoutine := 10 ch := make(chan string, numOfRoutine) for i := 0; i < numOfRoutine; i++ { go func(i int) { ch <- fmt.Sprintf("The result is from %d", i) }(i) } totalResult := "" for i := 0; i < numOfRoutine; i++ { // 阻塞式获取channel中的所有消息 totalResult += <-ch + "\n" } // 关闭channel close(ch) return totalResult } func AllResponseWithRange() string { numOfRoutine := 10 var wg sync.WaitGroup ch := make(chan string, numOfRoutine) for i := 0; i < numOfRoutine; i++ { wg.Add(1) go func(i int) { ch <- fmt.Sprintf("The result is from %d", i) wg.Done() }(i) } wg.Wait() // 关闭channel close(ch) totalResult := "" for v := range ch{ totalResult += v + "\n" } return totalResult } func TestGetAllResponse(t *testing.T) { //t.Log(AllResponse()) t.Log(AllResponseWithRange()) }
2020-07-15
1
NIXUS
@橙子 看了对象池这节中, 蓝士钦老哥的留言, 突然就明白该怎么写了. 老师说的去看 27 | channel的关闭和广播 这节也是有涉及这些内容, 只是一下子没找到重点(或者说关键点)在哪儿, 看完之后, 还是很懵, 一头雾水. 代码如下: var wg sync.WaitGroup func AllResponse() string { numOfRunner := 10 ch := make(chan string, numOfRunner) for i := 0; i < 10; i++ { wg.Add(1) go func(i int) { ch <- runTask(i) wg.Done() }(i) } finalStr := "" // for i := 0; i < numOfRunner; i++ { // finalStr += <-ch + "\n" // } go func() { for { if v, ok := <-ch; ok { finalStr += v + "\n" } else { break } } }() wg.Wait() return finalStr } func TestAllResponse(t *testing.T) { fmt.Print(AllResponse()) }
2019-04-03
收起评论