Go | 常见坑

Go | 常见坑

1. rand

import (
	"math/rand"
	"time"
)

var generator = rand.New(rand.NewSource(time.Now().Unix()))

func main() {
	go func() {
		for {
			generator.Int()
		}
	}()

	go func() {
		for {
			generator.Int()
		}
	}()

	time.Sleep(time.Second * 100)
}

Output

panic: runtime error: index out of range [-1]
...

我们使用rand.New创建随机数生成器不是线程安全,多协和同时访问会出现异常。直接使用rand包下的rand.Int()确不会有异常,是因为系统对rand.Int()做了包装,下面看下rand.Int()具体实现。

// 调用全局随机数生成器
func Int() int { return globalRand.Int() }

下面在看下globalRand定义,系统默认对Source外层用锁包裹,以此来达到并发访问安全。

var globalRand = New(&lockedSource{src: NewSource(1).(*rngSource)})

使用全局的rand注意在项目启动最开始使用随机数种子初始化,全局随机数生成器,代码如下。

func main() {
	// 初始化全局随机数种子
	rand.Seed(time.Now().Unix())
	fmt.Println(rand.Int()) // Output: 5496087833341174706
	fmt.Println(rand.Int()) // Output: 7529864966967492356
}

2. for

func myPrint(num *int) {
	fmt.Printf("num: %d point: %p\n", *num, num)
}

func main() {
	arr := []int{1, 2, 3, 4, 5}
	for _, v := range arr {
		// 整个for循环周期中变量v是共用一个
		// 每次循环相当于给v重新赋值
		go myPrint(&v)
	}

	time.Sleep(time.Second)
}

Output

num: 5 point: 0xc000018090
num: 4 point: 0xc000018090
num: 5 point: 0xc000018090
num: 5 point: 0xc000018090
num: 5 point: 0xc000018090

3. interface == nil

type A interface{}

type B struct{}

func main() {
	var b *B = nil
	var a A = b
	fmt.Println(a == nil) // Output: false
}

这里要简单说下接口实现,接口在Go语言中通过ifaceeface两个结构体实现,其中iface表示有接口方法的,eface表示没有接口方法的接口,接口内部实现如下。

type iface struct {
	tab  *itab
	data unsafe.Pointer
}

type eface struct {
	_type *_type
	data  unsafe.Pointer
}

而我们一但给一个接口赋值一个实例,哪怕实例是nil,接口中tab_type字段就有了当前实例的类型信息,接口就不能直接在与nil判断,可能使用如下方法判断。

type A interface{}

type B struct{}

func main() {
	var b *B = nil
	var a A = b
	fmt.Println(a == nil) // Output: false
	fmt.Println(IsNil(a)) // Output: true
}

func IsNil(a A) bool {
	if a == nil {
		return true
	}

	return reflect.ValueOf(a).IsNil()
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

方海峰的博客

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值