范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

golang2021数据格式(91)指针使用入门与unsafe。Pointer

  我们已经知道,变量的本质对一块内存空间的命名,我们可以通过引用变量名来使用这块内存空间存储的值,而指针则是用来指向这些变量值所在内存地址的值。
  注:变量值所在内存地址的值不等于该内存地址存储的变量值。
  和 PHP、Python、Java 不同,Go 语言支持指针,如果一个变量是指针类型的,那么就可以用这个变量来存储指针类型的值。
  简单示例
  我们来看一个简单的示例:
  a := 100
  var ptr *int // 声明指针类型
  ptr = &a // 初始化指针类型值为变量 a
  fmt.Println(ptr)
  fmt.Println(*ptr)
  上面代码中的 ptr 就是一个指针类型,表示指向存储 int 类型值的指针。ptr 本身是一个内存地址值,所以需要通过内存地址进行赋值(通过 &a 可以获取变量 a 所在的内存地址),赋值之后,可以通过 *ptr 获取指针指向内存地址存储的变量值(我们通常将这种引用称作「间接引用」),所以上述代码打印结果是:
  0xc0000a2000
  100
  每次打印的 ptr 值可能不一样,因为存储变量 a 的内存地址在变动,不同操作系统打印的结果也不相同。   PHP/Java 中也有类似通过 & 进行引用传值的用法,其实这种用法的本质也是指针,只不过 PHP/Java 在语言级别屏蔽了指针的概念而已。   Go 语言之所以引入指针类型,主要基于两点考虑,一个是为程序员提供操作变量对应内存数据结构的能力;另一个是为了提高程序的性能(指针可以直接指向某个变量值的内存地址,可以极大节省内存空间,操作效率也更高),这在系统编程、操作系统或者网络应用中是不容忽视的因素。   使用场景   指针在 Go 语言中有两个典型的使用场景:   类型指针   切片   作为类型指针时,允许对这个指针类型数据指向的内存地址存储值进行修改,传递数据时如果使用指针则无须拷贝数据从而节省内存空间,此外和 C 语言中的指针不同,Go 语言中的类型指针不能进行偏移和运算,因此更为安全。   切片类型我们前面已经介绍过,由指向数组起始元素的指针、元素数量和容量组成,所以切片与数组不同,是引用类型,而非值类型。   基本使用   下面我们以一个简单的示例代码来演示 Go 语言中指针的基本使用。   指针类型的声明和初始化   指针变量在传值时之所以可以节省内存空间,是因为指针指向的内存地址的大小是固定的,在 32 位机器上占 4 个字节,在 64 位机器上占 8 个字节,这与指针指向内存地址存储的值类型无关。   关于指针类型的声明我们在开头已经演示过,这里我们再回头看下这段代码:   var ptr *int   fmt.Println(ptr)   a := 100   ptr = &a   fmt.Println(ptr)   fmt.Println(*ptr)   当指针被声明后,没有指向任何变量内存地址时,它的零值是 nil,然后我们可以通过在给定变量前加上取地址符 & 获取该变量对应的内存地址,再将其赋值给声明的指针类型,这样,就完成对指针类型的初始化了,接下来我们可以通过在指针类型前加上间接引用符 * 获取指针指向内存空间存储的变量值。   当然,和所有其他 Go 数据类型一样,我们也可以通过 := 对指针类型进行初始化:   a := 100   ptr := &a   fmt.Printf("%p ", ptr)   fmt.Printf("%d ", *ptr)   底层会自动判断指针的类型,在格式化输出时,可以通过 %p 来标识指针类型。   此外,还可以通过内置函数 new 声明指针:   ptr := new(int)   *ptr = 100   通过指针传值   我们再来看一个通过指针传值的示例,通过指针传值就类似于 PHP/Java 中通过引用传值,这样做的好处是节省内存空间,此外还可以在调用函数中实现对变量值的修改,因为直接修改的是指针指向内存地址上存储的变量值,而不是值拷贝。   为了体现出区别,我们先看不使用指针的值拷贝示例:   func swap(a, b int) {   a, b = b, a   fmt.Println(a, b)   }   func main() {   a := 1   b := 2   swap(a, b)   fmt.Println(a, b)   }   上述代码的打印结果是:   2 1   1 2   下面我们通过指针传值来重构上述代码:   func swap(a, b *int) {   *a, *b = *b, *a   fmt.Println(*a, *b)   }   func main() {   a := 1   b := 2   swap(&a, &b)   fmt.Println(a, b)   }   上述代码的打印结果是   2 1   2 1   因为这次,我们是通过指针传值的(&a、&b 都是指针,只不过我们没有显示声明而已),直接会对内存地址存储变量值进行交换操作,而主函数中的 a、b 变量仅仅是对应内存存储空间的别名而已,所以调用完 swap 函数后,它们所对应的内存空间存储值已经交换过来了。   unsafe.Pointer   我们前面介绍的指针都是被声明为指定类型的,而 unsafe.Pointer 是特别定义的一种指针类型,它可以包含任意类型变量的地址(类似 C 语言中的 void 类型指针)。Go 官方文档对这个类型有如下四个描述:   任何类型的指针都可以被转化为 unsafe.Pointer;   unsafe.Pointer      可以被转化为任何类型的指针;   uintptr 可以被转化为 unsafe.Pointer;   unsafe.Pointer 可以被转化为 uintptr。   指针类型转化   因此,unsafe.Pointer 可以在不同的指针类型之间做转化,从而可以表示任意可寻址的指针类型:   i := 10   var p *int = &i   var fp *float32 = (*float32)(unsafe.Pointer(p))   *fp = *fp * 10   fmt.Println(i) // 100   这里,我们将指向 int 类型的指针转化为了 unsafe.Pointer 类型,再转化为 *float32 类型(参考前面的 unsafe.Pointer 转化规则 1、2)并进行运算,最后发现 i 的值发生了改变。   这个示例说明了 unsafe.Pointer 是一个万能指针,可以在任何指针类型之间做转化,这就绕过了 Go 的类型安全机制,所以是不安全的操作。   指针运算实现   此外,根据上面的转化规则 3、4,unsafe.Pointer 还可以与 uintptr 类型之间相互转化,为什么要单独列出这个类型呢?   uintptr 是 Go 内置的可用于存储指针的整型,而整型是可以进行数学运算的!因此,将 unsafe.Pointer 转化为 uintptr 类型后,就可以让本不具备运算能力的指针具备了指针运算能力:   arr := [3]int{1, 2, 3}   ap := &arr   sp := (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(ap)) + unsafe.Sizeof(arr[0])))   *sp += 3   fmt.Println(arr)   这里,我们将数组 arr 的内存地址赋值给指针 ap,然后通过 unsafe.Pointer 这个桥梁转化为 uintptr 类型,再加上数组元素偏移量(通过 unsafe.Sizeof 函数获取),就可以得到该数组第二个元素的内存地址,最后通过 unsafe.Pointer 将其转化为 int 类型指针赋值给 sp 指针,并进行修改,最终打印的结果是:   [1 5 3]   这样一来,就可以绕过 Go 指针的安全限制,实现对指针的动态偏移和计算了,这会导致即使发生数组越界了,也不会报错,而是返回下一个内存地址存储的值,这就破坏了内存安全限制,所以这也是不安全的操作,我们在实际编码时要尽量避免使用,必须使用的话也要非常谨慎。

名门修谱论辈分,堂表关系孰高孰低?孝道传承中国自古重孝道,因此在很多宗亲家族修谱的时候,家族辈分往往是特别要值得注意的。常言道不可乱了辈分,说的就是一个人的遵守基本的礼仪修养。辈分,是指在家族亲友的长幼先后中所居的华为发布首款商用5G折叠屏手机超级快充再次升级西班牙,巴塞罗那2月24日,华为在2019世界移动通信大会(MWC)正式发布具有划时代意义的5G折叠屏手机HUAWEIMateX,成为华为2019年发布的首款5G手机。HUAWEI名门修谱中国家谱进化史,互联网家谱这样来的家谱家谱,是以图录传记的方式,记载直系血缘关系及其一家源流世系和重要人物事迹的历史文化典籍。所以在很多人的眼里,家谱是人类文明的标志,也是人类历史形成的基础和源泉,更是一个家族文化颠覆行业!OPPOReno启用扇形摄像头专利,真好看只有想不到,没有OPPO做不到,在各家厂商挖孔,水滴,刘海翻来覆去使用的时候,OPPO却悄悄的在去年6月份,获得了前置扇形摄像头专利,这项专利也眼下在OPPOReno即将要被发布之名门修谱亲戚没碰面,也能修进家谱?确实可以传统家谱家谱对于一个家族来说非常重要,想把家谱一代代人传承下去,如何修谱又显得尤为的重要。可能说到修谱,很多人第一印象就是先搜集信息,然后再刻字排版,统一印刷,最后再修订成谱。没错选口红色号总是出错的男生们,白色情人节就不要再送口红了!对广大男性同胞来说,为妹子选口红可谓是一个千古难题!难以计数的品牌加上更加难以计数的色号这?确定不是专门来整我们的?因此网络上流传了很多关于直男选口红的悲惨段子,妹子们看后更是发出斯坦福深度学习训练及推理榜单华为云拿下双料冠军日前,斯坦福大学发布最新的DAWNBench榜单,华为云ModelArts一站式AI开发平台,获得图像识别训练和推理性能双料冠军,将模型训练时间大幅缩减的同时实现了超强推理性能,体拼多多提前开启618,百亿补贴击穿各种品牌底价,网友路转粉了距离全民狂欢618年中大促还剩下半个月的时间,各大电商平台统统卯足了劲,都争相打出了超低价的旗号。各类低价商品可谓是让不少消费者挑花了眼。那么,到底哪家平台的价格才是真正意义上的超轻旅行成为主流趋势,8英寸华为平板M5青春版走俏!近年来,人们开始对拥堵的高速公路人头攒动的景区那种长途奔袭式的景点游意兴阑珊。许多人渐渐意识到,那种上车睡觉,下车拍照的传统旅行方式其实远离了我们度假的初衷。于是,一种轻旅行慢慢流华为带来全新方舟编译器颠覆你对安卓系统的认知安卓系统与苹果系统之间的纷争,这么多年来可以说是打的难舍难分。从往年的情况来看,安卓系统总是摆脱不了用久就变卡的阴影。但就最近几年来看,安卓系统不断地在升级进化,如今可以说是已经于zol权威调查报告发布,华为平板M5青春版引领平板发展趋势作为IT3C行业的权威官方媒体,今日,中关村在线(zol)发布了最新的平板需求调查报告,全面梳理和分析了当下平板行业发展的趋势消费者关心关注的创新热点等内容,引发行业和消费者期待。
二手笔记本的选购指南教你最低价获得一台可用的笔记本电脑本文涉及二手笔记本,这部分市场过于小众,价格浮动水平较大,并且绝大部分需要个人有相应的动手能力。仅针对市面上x8664笔记本的选择进行介绍与推荐,文中所提及的价格水平仅供参考。本期又是一年双十二,和你谈一谈哪些高性能笔记本值得买本文不涉及二手笔记本工作站等设备,这部分市场过于小众,价格浮动水平较大故不做推荐。仅针对市面上新品x8664笔记本的选择进行介绍与推荐。本期文章中您将看到加强版前置科普2020Q4精准开发海外客户太费时间,有这必要吗?HaGro一站式AI智能获客外贸人,你现在是不是看完这句话,顿时晚饭就不香了?如何开发海外客户,相信你一定对精准开发四个字都嗤笑了。说我知道啊,谁不知道找客户要找优质对口的客户呢。花了几百钱购入了一台当年遥不可及的三星S8首先,就手感而言,三星S8是我认为到目前为止与小米6相似的手机,甚至比小米6还要好。尽管后指纹有点无味,但由于小巧,它仍然可以接受S8的大小。基本上可以用一只手在几秒钟内将其解锁,这几款机型性价比十足,尤其适合学生党,是你的菜吗?目前有很多5G手机,并且最近会有很多旗舰手机发布,但是对于学生聚会来说,预算真的很紧张,所以每个人都很难买到,所以实际上在今年1月三个是最值得购买的。中端神机既便宜又高端,非常适合适合学生党的三款千元机,性能强悍,价格良oppo和vivo这几年戴着价高配低的帽子,也受到不少网友的吐槽。但相比之下,还有一款性价比很高的机型,那就是小米。最近我整理了三款配置高价格低的机型,它们都是千元机,但是越来越认新手数据工程师常犯的5个错误微风简介在最佳的实践和业务调整方面,大多数新手数据工程师都是边学边做的。从构建太复杂而不可持续的系统,到过分信任现有的数据结构,下文中列出了五个最常见的错误和陷阱,即使是再熟练和天在北美攻读CS专业的国际学生美国研究生院以吸引国际学生而闻名。美国国家政策基金会(NFAP)的报告显示,国际学生占计算机和信息科学硕士学院的大多数比例,这可能会对未来几年科技公司寻找人才产生巨大的影响。这些国有了AI用户画像,还愁不能高效获客?跨境获客的目的是什么?不就是为了最终把潜在客户转化为目标客户,成功拿下订单吗?那你是否知道如何成功获客呢?首先,你得对所在行业市场有一定的了解,洞察出客户的需求其次,你得有庞大的待领英暂停中国会员注册,外贸人应该怎么办?3月10日消息,微软旗下职业社交网站领英(LinkedIn)周二称,为了确保公司遵守当地法律,公司将暂停在中国的新会员注册。领英暂停中国境内的新用户注册!?What?有多少外贸人被5G浪潮下怎么选择手机?中国移动硬件报告告诉你,实用第一随着我们的社会生活逐渐与5G深度交融,各种5G的概念及产品层出不穷,我国智能硬件市场再一次迎来了高速发展的阶段。在此5G浪潮的背景下,中国移动发布中国移动2020年智能硬件报告(第