概述
此文章记录用golang开发过程中需要注意的细节,陆续再增加。
1.int 和 int32 大小, int默认是int64,32位机器上默认是int32
var test int = 1
var test2 int32 = 1
println("len(test)=", unsafe.Sizeof(test))
println("len(test2)=", unsafe.Sizeof(test2))
打印:
len(test)= 8
len(test2)= 4
2.变量,常量
2.1 变量
var test type 定义一个type类型的变量test
var test type = value 定义变量并赋初始值
var test, test1 type 定义多个变量
2.2常量 在程序中不能被改变,一般定义为数值,布尔,字符串
const test int = 1
package main
const a int = 1
func main() {
println("a=", a)
a = 2 //编码就会报错
}
定义多个常量
package main
const (
a int = 1
b bool = false
)
func main() {
println("a=", a)
println("b=", b)
}
打印:
a= 1
b= false
3.iota是golang中的常量计数器,只能在常量表达式中使用, 在const关键字出现时被重置为0,每新增一行常量声明将使iota计数一次,在使用枚举的时候很有用
3.1
type result int8 //自定义枚举
const (
a result = iota
b
)
func main() {
println("a=", a)
println("b=", b)
}
a= 0
b= 1
3.2
iota也可以用于表达式,在常量中存储结果值
type result int8
const (
a result = 1 << iota //1<<0 1
b //1<<1 10
c //1<<2 100
)
func main() {
println("a=", a)
println("b=", b)
println("c=", c)
}
打印:
a= 1
b= 2
c= 4
4.channel 管道的阻塞,容易造成死锁
4.1 默认阻塞,如果满了,阻塞写,如果空了,阻塞读
验证:
func TestChannel(t *testing.T) {
ch := make(chan string)
go func() {
fmt.Printf("set ch start\n")
ch <- "hello world"
fmt.Printf("set ch end\n") //如果没有被主线程读走,就一直不会执行这里来,ch阻塞
}()
fmt.Printf("main start\n")
time.Sleep(time.Second * 5)
fmt.Printf("main end\n")
}
打印:
main start
set ch start
main end
4.2 遇到的坑
1.网络接包处理:一般客户端接收处理回包都是在统一的回调里面处理,如果一个协程没有及时处理,则会阻塞接收下一个包
2.模拟多客户端:2个协程用管道通信,如果一个协程等待另一个协程做完某些动作后才会走下一步,但是另一个协程没有通知到,导致这个协程一直阻塞等待,导致死锁
4.2 解决办法
1.给管道加缓冲
func TestChannel4(t *testing.T) {
ch := make(chan string, 2)
go func() {
fmt.Printf("set ch start\n")
ch <- "hello world"
fmt.Printf("set ch end\n") //有缓冲,没有满,则不阻塞
}()
fmt.Printf("main start\n")
time.Sleep(time.Second * 5)
fmt.Printf("main end\n")
}
打印:
main start
set ch start
set ch end
main end