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 语言从入门到实战
登录|注册
留言
38
收藏
沉浸
阅读
分享
手机端
回顶部
当前播放: 15 | 行为的定义和实现
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 | 结课测试&结束语
登录 后留言

全部留言(38)

  • 最新
  • 精选
蔡超
置顶
@ be humble 我是作者,刚才给你的回复有些错字。 你把String方法定义在结构上就可以了。 这样结构变量和指向结构的指针变量都可以用。如果你定义在指针上则只有输出指向结构的变量时起作用。
2019-03-13
6
面朝大海春暖花开
每天最期待的一件事就是:老师视频有没有更新!言简意赅,重点突出,对想学go 的java程序员而言简直是是量身定制的,太喜欢了。

作者回复: 谢谢你的鼓励!视频会一直持续更新的。

2019-03-13
11
虢國技醬
通过这节课纠正了自己对值接受者和指针接受者一个误区: 以前: 两者区别:1.值接受者声明的方法,调用时使用这个值的副本,指针接受者声明的方法,调用时共享这个值;2. 指针值可以调用值接受者声明方法,值不能调用指针接受者声明方法 现在: 两者区别:值接受者声明的方法,调用时使用这个值的副本,指针接受者声明的方法,调用时共享这个值 仔细验证发现不知道自己以前是在那里学到的第二点错误的知识,哎

作者回复: 👍

2019-09-22
2
9
蓝士钦
为结构体添加行为,建议采用非指针的方式,但是这种方式每次都会复制一份新的结构体,这样会有内存开销吧?感觉这种方式有点不科学。

作者回复: 我是视频中推荐的是采用指针的方式。第一种和和第二种视频中有说混,在视频最后我说明了一下,采用没有数据复制的写法。

2019-03-12
7
田佳伟
老师,如果使用引用的方式调用struct,假如修改了结构体里边的元素值,会污染到其他线程或者协程吗?是线程安全的吗?

作者回复: 看你传递的是不是指针,是指针就会。

2019-06-14
6
lupguo
这里有个问题咨询下老师,为什么下面代码的C结构体类型会有两处注释地方会有panic,而B结构体不会,这块嵌套有点混乱,希望老师指导下 // A type A struct{} func (a A) show() { fmt.Println("A call by show()") } func (a *A) ptShow() { fmt.Println("*A call by ptShow()") } // B type B struct { A } // C type C struct { *A } func main() { fmt.Println("test a, pa show:") a, pa := A{}, new(A) a.show() a.ptShow() pa.show() pa.ptShow() fmt.Printf("type of a(%T), pa(%T)\n", a, pa) //type B struct { // A //} fmt.Println("\ntest b, pb show:") b, pb := B{}, new(B) b.show() b.ptShow() pb.show() pb.ptShow() //type C struct { // *A //} fmt.Println("\ntest c, pc show:") c, pc := C{}, new(C) //c.show() //panic c为C类型 c.ptShow() //pc.show() //panic pc为*C类型, pc.ptShow() fmt.Printf("type of c.A(%T), pc.A(%T)\n", c.A, pc.A) }

作者回复: 这个是Go语言中比较令人困惑的部分, 1. 如果嵌入类型是结构,则从外部类型可以访问定义在结构及结构引用上的方法 2. 如果嵌入类型是结构的引用,则从外部类型仅可以访问定义在结构引用上的方法

2019-12-10
4
Dream.
幸苦老师帮忙解答一下。 为什么我定义一个链表temp:=new(ListNode),再定义了一个current:=temp current:=temp这样定义current的是值传递,current与temp本身的地址不是同一个地址,为什么他们的Next却是同一个地址呢? ============代码分割线================= package main import "fmt" //ListNode 定义一个链表结构 type ListNode struct {     Val int     Next *ListNode } func main() {     Linked() } //Linked 链表节点添加 func Linked() *ListNode {     temp := new(ListNode)     fmt.Printf("temp address is %x\n", &temp) //为什么是值传递,Next的地址却是同一个地址?     current := temp     fmt.Printf("current address is %x\n", &current)     current.Next = &ListNode{Val: 10, Next: nil}     fmt.Printf("current.Next address is %x and Val is %d\n", &current.Next, current.Next.Val)     fmt.Printf("temp.Next address is %x and Val is %d\n", &temp.Next, temp.Next.Val)     temp.Next = new(ListNode)     fmt.Printf("current.Next address is %x and Val is %d\n", &current.Next, current.Next.Val)     fmt.Printf("temp.Next address is %x and Val is %d\n", &temp.Next, temp.Next.Val)     return temp.Next }

作者回复: 原因是因为你是通过new创建的temp,所以temp其实是一个指针值,current复制了temp的指针(只是用了一个新的地址来保存这个指针值)所以他们同时指向的同一个ListNode 的实例。你改成 temp=ListNode{}试试

2019-03-23
4
蓝士钦
重新整理一下思路,非指针传递新的结构体(值复制),指针传递结构体地址(值为改结构体对象中的值),无论采用哪种方式都会觉得是值复制:其实非指针传递才是值复制,指针传递只是地址: type OperatingSystem struct { Name string } func (os OperatingSystem) LinuxFun(){ fmt.Printf("Address is %x\n", unsafe.Pointer(&os.Name)) os.Name = "Linux" // 非指针修改对象值,修改的是新的对象区域,不影响外部对象 fmt.Printf("Name:%s\n",os.Name) } func (os *OperatingSystem) WindowsFun(){ fmt.Printf("Address is %x\n", unsafe.Pointer(&os.Name)) os.Name = "Windows" // 指针修改对象值,修改的就是传进来的对象,影响外部对象 fmt.Printf("Name:%s\n",os.Name) } func TestStudent(t *testing.T) { os := OperatingSystem{Name:"MacOS"} fmt.Printf("Address is %x\n", unsafe.Pointer(&os.Name)) fmt.Printf("Name:%s\n",os.Name) // Name:MacOS os.LinuxFun() // 不使用指针地址不同, Name:Linux fmt.Printf("Name:%s\n",os.Name) // Name:MacOS os.WindowsFun() // 使用指针地址相同, Name:Windows fmt.Printf("Name:%s\n",os.Name) // Name:Windows }

作者回复: 非指针传递会生成一个新的结构对象,其中每个成员会复制。指针传递,只是传递指针,且该指针指向原有结构。

2019-03-13
2
2
为什么使用课件的code执行的结果,和老师视频演示的输出结构不一样的?是go版本的问题吗?希望老师能给个解答 === RUN TestCreateEmployeeObj encap_test.go:18: {0 Bob 20} encap_test.go:19: { Mike 30} encap_test.go:20: encap_test.go:21: &{2 Rose 22} encap_test.go:22: e is encap.Employee encap_test.go:23: e2 is *encap.Employee --- PASS: TestCreateEmployeeObj (0.00s) PASS Process finished with exit code 0

作者回复: 请粘贴一下以上结果执行的代码。

2020-10-30
李圣悦
package functest import ( "fmt" "math/rand" "reflect" "testing" "time" ) func returnMultiValues() (int, int) { return rand.Intn(10), rand.Intn(20) } func timeSpent(inner func(op int) int) func(op int) int { return func(n int) int { start := time.Now() ret := inner(n) fmt.Println("time spent: ", time.Since(start)) return ret } } func slowFun(op int) int { time.Sleep(time.Second * time.Duration(op/10)) return op } func TestMultiFunc(t *testing.T) { a, _ := returnMultiValues() t.Log(a) t.Log(timeSpent(slowFun)(10)) t.Log(reflect.TypeOf(time.Second).String()) } func Sum(ops ...int) int { ret := 0 for _, op := range ops { ret += op } return ret } func TestVarParam(t *testing.T) { t.Log(Sum(1, 2, 3, 4)) t.Log(Sum(1, 2, 3, 4, 5)) } func TestDefer(t *testing.T) { defer func(op int) int { t.Log("clean resources", op) return 0 }(5) t.Log("Started") panic("panic") //os.Exit(0) } 实测了一下,发现defer函数还可以有返回值,这个返回值能利用吗

作者回复: 看一下下面这个例子,你就会发现不要去使用defer来改变函数的返回。 package test_defer import ( "fmt" "testing" ) func EndByDefer() int { defer func() int { fmt.Println("defer is executed.") return 1 }() fmt.Println("running") return 2 } func TestReturnWithDefer(t *testing.T) { fmt.Println("The return is ", EndByDefer()) } 运行结果是: running defer is executed. The return is 2

2020-10-28
2
收起评论