golang基础(unsafe包使用)

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m0_38132420/article/details/78721345

前言

在使用C/C++过程中,很多时候出现的错误都是由于指针操作不合理,导致各种奇奇怪怪的问题。但是,也是由于指针的存在才让C/C++代码的运行效率比其他语言的略高。golang也有指针类型,但是不允许直接对指针类型进行运算。就是像保留指针的有点,规避掉由于指针操作不当而引发的各种奇怪问题。但是有些时候确实需要使用到指针运算的时候,就需要使用到unsafe包了。为什么要用unsafe包呢,说白了,就是让我们在操作指针的时候麻烦些,这样有一定几率会减少由于指针操作不当所引发的问题。

unsafe包接口介绍

1、func Alignof(x ArbitraryType) uintptr
获取变量以多数字节对齐
2、func Offsetof(x ArbitraryType) uintptr
Offsetof返回x所代表的结构体中字段的偏移量,它必须是structValue.field的形式。换言之,该方法返回结构体起始处到该字段之间的字节数。
3、func Sizeof(x ArbitraryType) uintptr
Sizeof获取变量的大小,类似于C/C++中使用sizeof(变量)返回的结果。

unsafe包中的类型

unsafe包中最重要的类型就是Pointer类型,定义如下:

type Pointer *ArbitraryType

**使用规律:
1)任何类型的指针可以转换为Pointer类型。
2)Pointer类型可以转换为任何类型的指针值。
3)uintptr和Pointer类型可以相互转换。
由于指针类型都是不可操作的,所以任意类型的指针必须转换为Pointer类型,然后再由Pointer类型转换为uintptr类型,由于uintptr类型不是指针类型,那么就可以进行运算了。运算完成后,把uintptr类型转换为Pointer类型后再转换为调用者想要的指针类型。**

如果运算后的uintptr运算出错,那就有可能造成代码逻辑混乱,甚至是出现panic。

使用总结

golang如果不使用unsafe包的时候,是不能进行指针运算的。作为比较新的语言,说明,确实在大部分开发过程中都不需要使用指针运算。只有在部分对性能特别敏感或者其他特殊情况下才需要使用指针操作。golang引入了unsafe包,个人觉得目的也是为了开发者在操作的指针的时候都一步操作,而不是直接就操作指针。会给开发者一个缓冲的时间,减少出错的概率。不过,其实对于一些指针操作老手来说,就显得有些多余了。

例子

unsafetest_test.go

package unsafetest

import (
    "fmt"
    "testing"
    "unsafe"
)

type Person struct {
    Age   int32  //年龄
    Name  string //名字
    Hobit string //爱好
}

func TestMytest(t *testing.T) {
    var personA Person
    var a byte
    //Alignof 示例
    align := unsafe.Alignof(a)
    fmt.Println("align is: ", align)
    //Sizeof 示例
    size := unsafe.Sizeof(a)
    fmt.Println("size is: ", size)
    //Offsetof 示例
    offset := unsafe.Offsetof(personA.Name)
    fmt.Println("offset is : ", offset)

    //Pointer 示例
    nameaddr := (uintptr)(unsafe.Pointer(&(personA.Name)))
    fmt.Println("nameaddr is: ", nameaddr)
    personAaddr := (uintptr)(unsafe.Pointer(&(personA)))
    fmt.Println("nameaddr is: ", personAaddr)
    personA.Age = 100
    personA.Hobit = "run"

    //指针操作 示例
    personAaddr2 := nameaddr - offset
    fmt.Println("personAaddr2 is: ", personAaddr2)
    personB := (*Person)(unsafe.Pointer(personAaddr2))
    fmt.Println("personB.Age is :", personB.Age)

    //异常情况 示例
    //... 中间逻辑使personAaddr2指向不合法位置
    personB = (*Person)(unsafe.Pointer(uintptr(0)))
    fmt.Println("personB.Age is :", personB.Age)
}

猜你喜欢

转载自blog.csdn.net/m0_38132420/article/details/78721345