全民制作人们大家好,我是练习时长两年半的个人练习生Barry Yan,喜欢唱、跳、Coding、羽毛球,Music!
今天给大家带来的这一档文章呢,主要是总结一下自己Coding过程中遇到的问题以及平时读一些博客的所得,因为做gopher也有了一段时间了,相比Java,有些问题的出现想要利用搜索引擎排查出来可能不是那么的迅速,所以在这里以文章的形式总结出来也方便各位初出茅庐的gopher们能够顺利的解决所遇到的问题,并能够习得一些小技巧。
为什么叫《Go语言开发小技巧&易错点100例》呢,说实话我也不知道能不能写到100例,只能说作为自己的一个小目标吧,先赚它一个亿,哈哈哈,只有目标才能促使自己不断Coding,不断发现和总结问题,相信到最后肯定要多于100个的,今天就先来4个!
先罗列一下吧(技巧类用【技】表示,易错点用【易】表示):
(1)return返回值屏蔽【技】
(2)context继承【易】
(3)禁止main退出【技】
(4)map遍历次序【易】
正文:
1 return返回值屏蔽【技】
返回值屏蔽的概念就是直接return也能返回函数的返回值,但是需要将返回值进行赋值操作,比如我们定义一个函数:func method(parm string) string
,返回值为string类型,实现函数时就会要求我们必须要return一个string类型的变量,但是如下的代码示例中直接一个return,并且也能正常执行
func Hello(name string) (str string) { str = "Hello World" if name != "" { return "Hello " + name } return } func main() { fmt.Println(Hello("")) fmt.Println(Hello("zs")) } 复制代码
运行结果:
Hello World Hello zs 复制代码
这就是返回值屏蔽的效果,但是要想实现,就必须也要像定义参数一样去定义返回值,如func method(parm string) res string
,就可以直接进行return了。
2 context继承【易】
众所周知,在Go开发中context包是一个很常用并且重要的包,
func Handler(ctx context.Context) { fmt.Println(ctx.Value("name")) fmt.Println(ctx.Deadline()) } func Controller(ctx context.Context) { fmt.Println(ctx.Value("name")) fmt.Println(ctx.Deadline()) ctx = context.WithValue(ctx, "name", "ls") ctx, _ = context.WithTimeout(ctx, time.Second*10) Handler(ctx) } func main() { ctx := context.WithValue(context.Background(), "name", "zs") ctx, _ = context.WithTimeout(ctx, time.Second*5) Controller(ctx) } 复制代码
运行结果:
zs 2022-10-15 14:38:46.0456413 +0800 CST m=+5.005663601 true ls 2022-10-15 14:38:46.0456413 +0800 CST m=+5.005663601 true 复制代码
context的部分规则如下:
- WithCancel:基于父级 context,创建一个可以取消的新 context。
- WithDeadline:基于父级 context,创建一个具有截止时间(Deadline)的新 context。
- WithTimeout:基于父级 context,创建一个具有超时时间(Timeout)的新 context。
- Background:创建一个空的 context,一般常用于作为根的父级 context。
- TODO:创建一个空的 context,一般用于未确定时的声明使用。
- WithValue:基于某个 context 创建并存储对应的上下文信息。
一般会有父级 context
和子级 context
的区别,我们要保证在程序的行为中上下文对于多个 goroutine
同时使用是安全的。并且存在父子级别关系,父级 context
关闭或超时,可以继而影响到子级 context
的程序。
3 禁止main退出【技】
方式一:
func main() { defer func() {for {}}() // TODO } 复制代码
方式二:
func main() { defer func() { select {} }() // TODO } 复制代码
方式三:
func main() { // TODO select {} } 复制代码
4 map遍历次序【易】
Go语言中map的遍历次序是无序的哈
func main() { m := make(map[string]string) m["A"] = "a" m["B"] = "b" m["C"] = "c" m["D"] = "d" m["E"] = "e" for i := range m { fmt.Println(i) } } 复制代码
运行结果:
C D E A B