Eslody

生活在树上-始终热爱大地-升入天空

  • 主页
  • 随笔
所有文章 关于我

Eslody

生活在树上-始终热爱大地-升入天空

  • 主页
  • 随笔

go unsafe.Pointer和uintptr解析

2021-06-09

记录最近遇到的一些问题

定义

1.普通指针:*类型代表普通指针,用户传递对象的地址,但是不能进行指针的运算。

2.unsafe.Pointer:通用的指针类型,可以转换成任意的指针类型。不能进行指针的运算,也不能读取存储的值。如果要读取内存存储的值,需要转化为普通指针,再取值。

3.uintptr:可用于指针运算。并不是指针,可以将unsafe.Pointer指针转化为uintptr类型(是和当前指针相同的一个数字值),然后进行指针运算。

unsafe.Pointer

首先见官方文档给出的四个描述:

1.任何类型的指针都可以被转化为Pointer

2.Pointer可以被转化为任何类型的指针

3.uintptr可以被转化为Pointer

4.Pointer可以被转化为uintptr

普通的指针类型会写出T,表示是一个指向T类型变量的指针。而Pointer是一种特别定义的指针类型,它可以包含任意类型变量的地址。同时这也意味着我们无法通过”*p”的格式来获取指针指向的值,因为不知道具体的类型。Pointer指针是可比较的

关于官方文档中1、2两点,值得注意的是,普通的指针类型通过转向Pointer后再次转回指针类型,两次指针类型不需要相同

1
2
3
4
5
6
func main()  {
h := 1
p := &h
var l *int64 = (*int64)(p)
}
//编译通不过,因为go是一门强类型的静态语言。类型一旦定义了就不能变了,类型检查会在运行前进行。因此go不允许两个指针类型进行转换
1
2
3
4
5
6
func main()  {
h := 1
p := &h
var l *int64 = (*int64)(unsafe.Pointer(p))
}
//如果要编译通过则需要先转换成Pointer类型

uintptr

uintptr是golang内置的一种存储指针的无符号整型类型。个人理解,它代表当前指针所指向的内存地址,以便于进行某种指针类型的运算。按照如上官方文档给出的描述,虽然uintptr可以转成Pointer,但由于并不是所有内存地址都是有效的,所以并不安全

下面是一个典型的uintptr使用案例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
package main

import (
"fmt"
"unsafe"
)

func main() {
var x struct {
a bool
b int16
c []int
}
//unsafe.Offsetof 函数表示,对于参数x.f,返回 f 字段相对于 x 起始地址的偏移量
//uintptr(unsafe.Pointer(&x)) + unsafe.Offsetof(x.b)代表指针的运算
//这里等价于pb := &x.b
pb := (*int16)(unsafe.Pointer(uintptr(unsafe.Pointer(&x)) + unsafe.Offsetof(x.b)))
*pb = 42
fmt.Println(x.b) // "42"
}

这里引出另外一个问题:不要试图设一个uintptr的临时变量!因为当垃圾回收器进行移动GC时,所有的保存某变量旧地址的指针必须同时被更新为变量移动后的新地址。而uintptr类型的临时变量只是一个数字,并不持有对象。垃圾回收器无法识别这是个指向变量t的指针。当变量t被移动后,临时变量的值就已经不是变量t的地址了。再使用临时变量就会出现不可预测的错误。

赏

谢谢你请我吃糖果

  • go

扫一扫,分享到微信

微信分享二维码
转发://深入理解Golang
net/http源码阅读
  1. 1. 定义
  2. 2. unsafe.Pointer
  3. 3. uintptr
© 2021 eslody
To be or not to be.
  • 所有文章
  • 关于我

tag:

  • 数据结构与算法
  • java
  • Linux
  • 操作系统
  • 计算机网络
  • 区块链
  • go
  • 工具
  • 分布式
  • 实习记录
  • 随笔
  • http
  • RPC
  • Gin

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

  • QUIC协议原理浅析

    2021-07-11

    #计算机网络#http

  • 基数树(Radix tree)和前缀树(Trie tree)

    2021-07-10

    #Gin

  • 转发://http2.0多路复用

    2021-07-08

    #http

  • bufio包原理解析

    2021-07-08

    #go

  • 为什么response.Body.Close()是必要的

    2021-06-29

    #go

  • 记一次代码优化的经历

    2021-06-25

    #实习记录#随笔

  • syn/singleflight源码阅读

    2021-06-21

    #go

  • 转发://深入理解Golang

    2021-06-12

    #go

  • go unsafe.Pointer和uintptr解析

    2021-06-09

    #go

  • net/http源码阅读

    2021-06-04

    #go

  • MapReduce的一些改进

    2021-05-25

    #go#分布式

  • 转发://推荐几个巨强的大佬博客(持续更新)

    2021-05-15

  • RPC项目的流程图

    2021-05-14

    #RPC

  • 关于快速选择的尾递归

    2021-03-25

    #数据结构与算法

  • 实现一个MapReduce

    2021-03-22

    #go#分布式

  • 1~n整数中1出现的次数

    2021-03-09

    #数据结构与算法

  • 一些有关快排的小问题

    2021-03-06

    #数据结构与算法

  • IO多路复用详解

    2021-03-05

    #Linux#操作系统#计算机网络

  • 聊聊虚拟内存

    2021-03-04

    #操作系统

  • 正则表达式(Regular Expression)

    2021-03-03

    #工具

  • go指南——练习:web爬虫

    2021-03-02

    #go

  • printf执行原理

    2021-02-24

    #操作系统

  • SYN洪泛攻击原理及防御

    2021-02-23

    #计算机网络

  • Arrays.asList基本用法

    2020-12-12

    #java

  • 从暴力递归到动态规划(二)

    2020-12-11

    #数据结构与算法

  • 从暴力递归到动态规划(一)

    2020-12-11

    #数据结构与算法

  • 线段树(区间修改树)

    2020-12-08

    #数据结构与算法

  • 理解https

    2020-11-18

    #计算机网络

  • Solidity实现以太坊秘密竞拍智能合约

    2020-10-03

    #区块链

热爱跳舞

永远是学徒