Go不安全编程

场景一:对接C程序

大多数都是用于外部C程序实现的一些高效的库进行叫交互式会用到unsafe

场景二:指针类型转换

“不安全”行为的危险性:go 语言中是不支持强制类型转换的,但是我们使用 unsafe 是可以把一个类型的指针强行转化为任意类型的指针的

package unsafet_test

import (
	"fmt"
	"sync"
	"sync/atomic"
	"testing"
	"time"
	"unsafe"
)

// 不合理转换
func TestUnsafe(t *testing.T) {
	i := 10
	f := *(*float64)(unsafe.Pointer(&i))
	t.Log(unsafe.Pointer(&i))
	t.Log(f)
}

// 合理的类型转换
type MyInt int

func TestConvert(t *testing.T) {
	a := []int{1, 2, 3, 4}
	b := *(*[]MyInt)(unsafe.Pointer(&a))
	t.Log(b)
}

// 指针原子类型操作
// 场景:并发读写共享缓存时,为了达到读与写的安全性
// 当写的时候我们写在一个新的内存地址,写完之后用原子操作
// 把读的指针指向新的内存地址
func TestAtomic(t *testing.T) {
	var shareBufPtr unsafe.Pointer // 共享内存地址
	writeDataFn := func() {
		var data []int
		for i := 0; i < 100; i++ {
			data = append(data, i)
		}
		//fmt.Println(unsafe.Pointer(&data))
		atomic.StorePointer(&shareBufPtr, unsafe.Pointer(&data))
	}
	readDataFn := func() {
		data := atomic.LoadPointer(&shareBufPtr)
		fmt.Println(data, *(*[]int)(data))
	}
	var wg sync.WaitGroup
	writeDataFn()
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func() {
			for i := 0; i < 10; i++ {
				writeDataFn()
				time.Sleep(time.Millisecond * 100)
			}
			wg.Done()
		}()
		wg.Add(1)
		go func() {
			for i := 0; i < 10; i++ {
				readDataFn()
				time.Sleep(time.Millisecond * 100)
			}
			wg.Done()
		}()
	}
}

上面代码中的最后一个测试程序,我在 win10 系统中要运行多次才能拿到理想中的结果,好难受啊

posted @ 2020-01-07 18:02  黄土地上的黑石头  阅读(228)  评论(1编辑  收藏  举报