开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第10天,点击查看活动详情
先罗列一下吧(技巧类用【技】表示,易错点用【易】表示):
(1)main函数提前退出【易】
(2)包循环依赖【易】
(3)fallthrough关键字【技】
(4)简式变量声明(i:=1)仅能在函数内部使用【易】
(5)interface断言【易】
正文:
1 main函数提前退出【易】
你是否遇见过这种情况:
func main() {
go func() {
fmt.Println("Hello goruntine")
}()
fmt.Println("Hello main")
}
运行结果:
第一次运行:
Hello main
第n次运行:
Hello main
Hello goruntine
第n+1次运行:
Hello goruntine
Hello main
为什么会导致这样的结果呢?
答案就是多线程,并且他们的线程并不是互斥的。
解决方式:
不专业的方式
func main() {
go func() {
fmt.Println("Hello goruntine")
}()
fmt.Println("Hello main")
time.Sleep(time.Second * 5)
}
专业的方式
func main() {
group := sync.WaitGroup{}
group.Add(1)
go func() {
defer group.Done()
fmt.Println("Hello goruntine")
}()
fmt.Println("Hello main")
group.Wait()
}
2 包循环依赖错误【易】
先说明下场景:
我们在dao层的文件中定义结构体和其相关的dao层方法,但是在调用方法时(如插入数据的方法)会使用utils包中的工具方法对参数进行检查,而utils中的工具方法需要引用dao层的结构体才能够检查,因此出现了dao依赖utils包,utils包依赖dao包的情况,就导致了循环依赖的异常。
dao包文件:
package dao
import (
"fmt"
"other/article/utils"
)
type User struct {
Name string
}
func InsertUser() {
utils.CheckUser()
fmt.Println("InsertUser")
}
utils包文件:
package utils
import (
"fmt"
"other/article/dao"
)
func CheckUser() {
user := dao.User{Name: "zs"}
fmt.Println("CheckUser", user)
}
main文件:
package main
import (
"other/article/dao"
)
func main() {
dao.InsertUser()
}
运行结果:
package command-line-arguments
imports other/article/dao
imports other/article/utils
imports other/article/dao: import cycle not allowed
解决方式:
将dao层的结构体移到一个新包中,并且dao和utils都引用这个新包。
这个错误也告诉我们一个道理,就是代码要注意划分层次,低内聚,才能更好的增加代码的可读性。
3 fallthrough关键字【技】
Go里面switch默认相当于每个case最后带有break,匹配成功后不会自动向下执行其他case,而是跳出整个switch, 但是可以使用fallthrough强制执行后面的case代码。
func main() {
i := 10
switch i {
case 1:
fmt.Println(1)
case 5:
fmt.Println(5)
fallthrough
case 10:
fmt.Println(10)
fallthrough
case 20:
fmt.Println(20)
default:
fmt.Println("default")
}
}
运行结果:
10
20
4 简式变量声明仅能在函数内部使用【易】
什么是简式变量声明呢,我们知道Go声明变量有两种方式
// 第一种
var i int
i = 10
// 第二种 (简式变量声明)
i := 10
而第二种变量声明就不可以在方法外使用
5 interface断言【易】
func main() {
var value interface{}
value = "hello"
str := value.(string)
fmt.Println(str)
value = 100
i := value.(int32)
fmt.Println(i)
}
运行结果:
hello
panic: interface conversion: interface {} is int, not int32
......
解决方式:
在断言之前先做一个类型判断
func main() {
var value interface{}
value = 100
switch value.(type) {
case int32:
fmt.Println(value.(int32))
case string:
fmt.Println(value.(string))
case int:
fmt.Println(value.(int))
}
}
当然GitHub有更好的方式可以将interface类型转化成我们需要的类型,比如cast插件。
今天的分享就到这里咯~
参考: