unsafe包

简介: go语言的指针类型分为三种:(1)普通指针类型:*类型,用于存储地址,不能进行指针运算(2)通用指针类型:用于转换不同类型的指针,不能进行指针运算(3)uintptr:用于指针运算,GC不把uintptr当指针,uintptr无法持有对象。

go语言的指针类型分为三种:
(1)普通指针类型:*类型,用于存储地址,不能进行指针运算
(2)通用指针类型:用于转换不同类型的指针,不能进行指针运算
(3)uintptr:用于指针运算,GC不把uintptr当指针,uintptr无法持有对象。uintptr对象会被回收。
unsafe.Pointer 可以和普通指针进行转换。
unsafe.Pointer 可以和 uintptr 进行相互转换。

也可以说 unsafe.Pointer 是桥梁,可以让任意类型的指针实现相互转换,也可以将任意类型的指针转换为uintptr进行指针运算。

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    s := struct {
        i   int
        b   bool
        str string
    }{1, true, "hello"}
    fmt.Println("原来s变量的内容为:", s)
    // 转换成通用指针
    p := unsafe.Pointer(&s)
    // 转换成uintpre类型
    up0 := uintptr(p)
    // 将uintpre类型转换成int指针类型
    pi := (*int)(p)
    *pi = 10
    fmt.Println(s)

    // 偏移到结构体下标b位置,p1类型为uintptr
    p1 := up0 + unsafe.Offsetof(s.b)
    // 将uintptr转化成通用指针
    p = unsafe.Pointer(p1)
    // 将通用指针类型转化成bool指针类型
    pb := (*bool)(p)
    *pb = false
    fmt.Println(s)

    // 偏移到结构体下标str位置,p2类型为uintptr
    p2 := up0 + unsafe.Offsetof(s.str)
    // 将uintptr类型转化成通用类型指针
    p = unsafe.Pointer(p2)
    // 将通用指针类型转换成string指针类型
    ps := (*string)(p)
    *ps = "hello world"
    fmt.Println(s)
}

结构体成员的内存分配是连续的,第一个成员的地址就是结构体的地址,相对结构体的偏移量为0。其他成员都可以通过偏移量来计算其地址。
每种类型都有它的大小和对齐值,可以通过unsafe.Sizeof获取其大小,通常unsafe.Alignof获取其对齐值,通过unsafe.Offsetof获取其偏移量。不过unsafe.Alignof获取到的对齐值只是该类型单独使用时的对齐值,不是作为结构体字段时与其它对象间的对齐值,这里用不上,所以需要用unsafe.Offsetof来获取字段的偏移量,进而确定其内存地址。

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    s := struct {
        i   int
        b   bool
        str string
    }{1, true, "hello"}
    fmt.Println("s变量内容:", s)
    fmt.Println("变量s的大小:", unsafe.Sizeof(s))
    fmt.Println("s.i的大小:", unsafe.Sizeof(s.i))
    fmt.Println("s.b的大小:", unsafe.Sizeof(s.b))
    fmt.Println("s.str的大小:", unsafe.Sizeof(s.str))
    fmt.Println("-------------------------------")
    fmt.Println("s.i的偏移量:", unsafe.Offsetof(s.i))
    fmt.Println("s.b的偏移量:", unsafe.Offsetof(s.b))
    fmt.Println("s.str的偏移量:", unsafe.Offsetof(s.str))
    fmt.Println("-------------------------------")
    fmt.Println("变量s的对齐:", unsafe.Alignof(s))
    fmt.Println("s.i的对齐:", unsafe.Alignof(s.i))
    fmt.Println("s.b的对齐:", unsafe.Alignof(s.b))
    fmt.Println("s.str的对齐:", unsafe.Alignof(s.str))
}

参考:https://www.cnblogs.com/golove/p/5909968.html

目录
相关文章
|
6月前
|
安全 Java API
14.JDK底层Unsafe类是个啥东西?
14.JDK底层Unsafe类是个啥东西?
81 0
14.JDK底层Unsafe类是个啥东西?
|
1月前
|
安全 Java
unsafe类和varhandle类讲解
本文介绍了Java中的Unsafe类和VarHandle类,展示了Unsafe类如何通过底层操作绕过Java的安全限制直接访问内存和对象,以及VarHandle类如何在Java 9及以上版本中提供原子性和可变性访问。
24 1
unsafe类和varhandle类讲解
|
3月前
|
存储 Java 编译器
深入理解 go unsafe
深入理解 go unsafe
26 0
|
Java API
【Unsafe】
【Unsafe】
|
安全 Go 开发者
Go 语言使用标准库 sync 包的 mutex 互斥锁解决数据静态
Go 语言使用标准库 sync 包的 mutex 互斥锁解决数据静态
53 0
|
存储 安全 编译器
Go语言源码剖析-String和unsafe包
Go语言源码剖析-String和unsafe包
73 0
|
Oracle 前端开发 算法
JDK源码(21)-Unsafe
JDK源码(21)-Unsafe
178 0
JDK源码(21)-Unsafe
|
Java
CAS之什么是unsafe类(三)
CAS之什么是unsafe类(三)
208 0
CAS之什么是unsafe类(三)
|
存储 Java Go
go unsafe包的使用
使用unsafe包修改数据
106 0