随笔 - 241  文章 - 1  评论 - 58  阅读 - 85万 

前言

在Go里面pointer就是1种可以把内存地址的存储起来的数据类型。我们使用pointer数据类型的变量可以记录下另1个变量的内存地址,方便我们修改这变量的值。

 

为什么Go中使用了指针?

因为指针可以帮助我们节省内存,我们知道在程序运行时值类型的变量被赋值之后会对值进行重新拷贝,如果我们每次拷贝的是1个指针类型的变量呢?

还有Go函数里面传递的参数都是副本也就是重新copy一份,我们如何在函数中修该1个外部变量。我们可以通过记录下值类型变量的内存地址,来达到修改值类型变量的目的。

 

区别于C/C++中的指针,Go语言中的指针不能进行偏移和运算,只能读取指针的位置,是安全指针,所有Go里面的指针比较简单。

还有很重要的一点就是我们可以对1个真正存储值的变量,设置多个指针,就可以做引用数据类型。起到节省内存的效果。

 

只需要记住以下几点:

&变量名: 获取变量的内存地址

*pointor:通过指针类型的变量,获取该指针指向的值

v1:="张根"
p1:=&v1
fmt.Println(v1,p1,*p1)
//张根 0xc0001041e0 张根

 

什么是指针

 

 

不管是Python还是Go程序 执行过程中数据(变量)载入内存后,在计算机内存中都有该变量所在的内存地址,这就是指针。

var v3 *int
v4:=new(int)

 

 

 

指针就是1个保存了另1个变量所在内存地址的变量,该变量记录了X\y\a\s变量的内存地址,我们就可以通过指针变量在广袤的内存上快速查找到X\y\a\s变量。对其就行修改。

  

在Go语言中的值类型(int、float、bool、string、array、struct)都有对应的指针类型,如:*int*int64*string等。

 

指针操作

package main
 
import "fmt"
 
func main() {
    //基本数据类型在内存中的布局
    var i int = 10
    //获取变量i的内存地址
    fmt.Println("变量i的内存地址:", &i)
    //声明1个 ptr指针变量,指向1个类型为int的内存地址
    var ptr *int = &i
    fmt.Println(ptr)
    //获取指针的内存地址
    fmt.Println(&ptr)
    //通过指针获取变量i对应的值(10)
    fmt.Println(*ptr)
    //通过指针修改变量i对应的值
    *ptr = 222
    fmt.Println(i)
 
    //通过指针修改变量的值
    name := "成龙"
    age := "18"
 
    por1 := &name
    *por1 = "JackCheng"
    por1 = &age
    *por1 = "68"
    fmt.Println(name, age)
 
}

 

golang的指针是安全的默认不能进行偏移和运算,只能读取指针的位置。但是如果它变成unsafe的也是可以的。

复制代码
package main

import (
    "fmt"
    "reflect"
    "unsafe"
)

func main() {
    //数组是一块连续的内存,第1个元素的内存地址代指整个数组
    userList := [3]int8{11, 22, 33}
    //但是数组的第1个元素和数组的指针类型不同
    //*[3]int8
    //*int8
    fmt.Println(reflect.TypeOf(&userList))
    fmt.Println(reflect.TypeOf(&userList[0]))
    //0xc000062330 0xc000062340 0xc000062350
    fmt.Println(&userList[0], &userList[1], &userList[2])
    //1.获取数组第1个元素的内存地址
    var firstItemPtr *int8 = &userList[0]
    //2.转换成Pointer类型
    ptr := unsafe.Pointer(firstItemPtr)
    //3.转换成uintptr类型,然后进行内存地址计算(即地址增加1个字节,意味着2个索引位置)
    targetAdress := uintptr(ptr) + 1
    fmt.Println(targetAdress)
    //4.根据新地址重新转换成Pointer类型
    newPtr := unsafe.Pointer(targetAdress)
    //5.Pointer对象转换成 int8指针类型
    value := (*int8)(newPtr)
    fmt.Println(*value)

}
复制代码

 

  

 

 

 

 

new和make的区别

前面我知道使用make可以创建1个切片数据类型的变量,并且该slice在没有赋值前,就有默认值(开辟了内存空间);

make 和new在Go中都是用于申请内存的

new用于给Go中基本的数据类型申请内存(int/string/bool)返回的是对应数据类型的指针(*int/*string/*bool)

 

make用于给复杂数据类型申请内存(slice/map/chanel/struct),返回值=默认值的数据类型本身。

 

 

 

  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

see also

posted on   Martin8866  阅读(1199)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· SQL Server 2025 AI相关能力初探
· AI编程工具终极对决:字节Trae VS Cursor,谁才是开发者新宠?
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
点击右上角即可分享
微信分享提示