首页 > 其他分享 >go 使用 unsafe 包

go 使用 unsafe 包

时间:2023-06-25 11:55:29浏览次数:31  
标签:int type 使用 unsafe var uintptr go Pointer

go 使用 unsafe 包进行指针操作

go 语言中没有直接提供指针操作,但是提供了 unsafe 包可以对指针进行转换

//	- A pointer value of any type can be converted to a Pointer.
//	- A Pointer can be converted to a pointer value of any type.
//	- A uintptr can be converted to a Pointer.
//	- A Pointer can be converted to a uintptr.

前置知识

unsafe 包中几个类型的定义

package unsafe

// ArbitraryType is here for the purposes of documentation only and is not actually
// part of the unsafe package. It represents the type of an arbitrary Go expression.
type ArbitraryType int

// IntegerType is here for the purposes of documentation only and is not actually
// part of the unsafe package. It represents any arbitrary integer type.
type IntegerType int

type Pointer *ArbitraryType

uintptr 类型的定义

// uintptr is an integer type that is large enough to hold the bit pattern of
// any pointer.
type uintptr uintptr

提供的指针操作

官方文档一共提供有四中方式

  1. 指针转换成 Pointer; *T -> Pointer
  2. Pointer 转换成指针; Pointer -> *T
  3. uintptr 转换成Pointer; uintptr -> Pointer
  4. Pointer 转换成uintptr; Pointer -> uintptr

普罗米修斯监控中,使用 uint64 来代表 float64 的存储,

type histogramCounts struct {
	// sumBits contains the bits of the float64 representing the sum of all
	// observations. sumBits and count have to go first in the struct to
	// guarantee alignment for atomic operations.
	// http://golang.org/pkg/sync/atomic/#pkg-note-BUG
	sumBits uint64
	count   uint64
	buckets []uint64
}
func Float64bits(f float64) uint64 {
    return *(*uint64)(unsafe.Pointer(&f))
}

指针加减来获取数组的值

func TestXx1(t *testing.T) {
	var a int = 5
	var b float64 = 5.99
	var c [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	var f Foo

	var p1 = (unsafe.Pointer)(&a)
	var p2 = (unsafe.Pointer)(&b)
	var p3 = (unsafe.Pointer)(&c)
	var p4 = (unsafe.Pointer)(&f)
	t.Log(p1, p2, p3, p4)

	for i := 0; i < len(c); i++ {

		pp := unsafe.Pointer((uintptr(p3) + uintptr(i)*unsafe.Sizeof(c[i]))) // 当前下标对应的地址

		pt := *(*int)(pp) + 3
		*(*int)(pp) = *(*int)(pp) + 1 // 重新设置值

		t.Log(pp, " => ", *(*int)(pp), pt, "    => ", c[i], "   => ", uintptr(i))

	}
}

执行结果
img


判断当前结构体是否实现接口

type test struct{}
type i interface {
	Name() string
}

func (*test) Name() string {
	return "test"
}
func TestIsImp(t *testing.T) {

	var _ i = (*test)(nil) // 如果未实现,在编译时就会报错
	var tt i = &test{}

	t.Log(tt.Name())
}

字符串转换


func TestS2B(t *testing.T) {
	var s = "123456"
	t.Log((*[]byte)(unsafe.Pointer(&s)))
	t.Log(*(*[]byte)(unsafe.Pointer(&s)))
}

标签:int,type,使用,unsafe,var,uintptr,go,Pointer
From: https://www.cnblogs.com/sooooooul/p/17502569.html

相关文章

  • Linux操作系统怎么使用Windows下的字体
    Linux系统如果需要使用Windows下字体可以使用以下方法例如Linux下应用WPS需要使用微软雅黑字体则首先到windows下的目录C:\Windows\Fonts找到微软雅黑字体右键复制微软雅黑字体,会复制三个字体文件把这三个文件复制到Linux系统的以下目录/usr/share/fonts/wps-office重启......
  • Redis缓存使用技巧和设计方案?薪火数据知识库
    Redis是一种开源的内存数据库,被广泛应用于缓存系统设计和实现中。它提供了高性能、低延迟的数据访问,并支持多种数据结构和丰富的功能。下面将详细介绍Redis缓存的使用技巧和设计方案。一、Redis缓存基本原理:数据存储结构:Redis支持多种数据结构,如字符串(String)、哈希(Hash)、列......
  • Openssl安装使用(三):OpenSSL安装常见问题
    (1)执行Configure命令(配置编译参数)”perlconfigureVC-WIN32”遇到如下问题:Can'tlocalWin32/Console.pemin@INC(youmayneedtoinstalltheWin32:Consolemodule)(@INC contains:C:\Perl64\site\libC:\Perl64\lib)atC:\Perl64\lib/ActivePerl/Config.pmline400.......
  • Solr使用性能优化设想
    如果全量数据和增量数据有指定时间,默认近一个月1.是否可以通过集合名称中指定当前月份和上月集合,作为一个客户端,如果不行,可以考虑建立别名,该别名中只有近两个月的集合。 2.其他关系表,更新数据时尽量少从solr中查询,,最后时间以当前的即可(应为bcp文件处理时是有顺序的))、参数(直......
  • 多分类模型训练使用交叉熵损失的一个注意的点
    使用交叉熵损失的网络模型最后一层不要用softmax,交叉熵损失函数会在计算的时候做softmax,如果用了会导致模型训练异常,如果模型最后一层有softmax,则损失函数要写成loss_fun=nn.NLLLoss()x=model(data)loss=loss_fun(torch.log(x),label) ......
  • 放弃使用forEach的理由
    js中Array的forEach有如下缺点1.不支持异步,内部用await无效2.无法中断,不支持break,continue3.跳过已删除和未初始化的项4.不能修改数组项替代方案1.map()、filter()、reduce()支持异步,for循环和forof都支持异步constpromises=arr.map(async(num)=>{constres......
  • candence计算器函数使用
    (91条消息)【工具小技巧】CadenceVirtuosoCalculatorFunctionPanel计算器函数功能介绍(持续更新……)_cadence计算器函数_喝喝喝水的博客-CSDN博客......
  • 使用Echarts时报 Implementation of registerMap doesn't exists 错误解决办法
    最新的echarts在使用时,如果使用按需加载的方式引入依赖。在使用registerMap函数时会报错如果出现这两个错误:ImplementationofregisterMapdoesn'texists.或者Mapxxxnotexists.TheGeoJSONofthemapmustbeprovided.那么大概率是因为echarts升级后导致的不兼容问题。......
  • 【已解决】GO语言开发中调用另一个库报错 cannot refer to unexported name XXXX
    packagemainimport( "fmt" "study_gos/main/kehu")//使用了go.mod//GOPATH;D:\workspace\studys\study_gos//cd/d/workspace/studys/study_gos/src//goenv-wGO111MODULE=on//gomodinitstudy_gos//gomodtidy//跳过goget失败//go......
  • GO 语言中 slice 的理解
    GO语言中 slice理解为什么说Go语言的slice是引用类型,其底层实现明明是一个结构体?slice的底层实现是一个包含三个字段的结构体:指向底层数组的指针、slice的长度和slice的容量。当我们对slice进行操作时,例如添加或删除元素,实际上是在底层数组中进行操作。由于slice......