GoLong的学习之路(六)语法之指针

书接上回,上回书中写道,数组已经和java中数组的区别。在go中数组的是数值类型,故需要指针指向数组的地址,从而进行修改。这次诉说,指针

指针

区别于C/C++中的指针,Go语言中的指针不能进行偏移和运算,是安全指针。(难度直接向下)

要搞明白Go语言中的指针需要先知道3个概念:指针地址、指针类型和指针取值。

指针地址

在内存中,一个数据需要存储,但是不能光存储,不去处理。要处理就必须在众多的数据中锁定我们所需的数据,这个就像,是在茫茫人海中一眼就看到你(只在灯火阑珊处)。所以此时就需要一个能够找到你的位置,也就是--------地址(在内存中,地址通常以32位,16进制表示)

我在程序中把赋值给变量A,把内存地址赋值给变量B。这时候变量B就是一个指针变量。

Go语言中的指针不能进行偏移和运算,因此Go语言中的指针操作非常简单,我们只需要记住两个符号:&(取地址)(获取引用)和 *(根据地址取值)(解引用)。

每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。

  • Go语言中使用 & 字符放在变量前面对变量进行“取地址”操作。

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

func main() {
	a := 10
	b := &a
	fmt.Printf("a:%d ptr:%p\n", a, &a) // a:10 ptr:0xc00001a078
	fmt.Printf("b:%p type:%T\n", b, b) // b:0xc00001a078 type:*int
	fmt.Println(&b)                    // 0xc00000e018
}

a :代表被取地址的变量,类型为 int
b:用于接收地址的变量,ptr的类型就为 *int,称做 int 的指针类型。*代表指针。

在这里插入图片描述

变量、指针地址、指针变量、取地址、取值的相互关系和特性:

  • 对变量进行进行取地址( & )操作,可以获取这个变量的指针变量
  • 指针变量的值是指针地址
  • 对指针变量进行取值( * )操作,可以获取指针变量指向的原变量的值
func main() {
	//指针取值
	a := 10
	b := &a // 取变量a的地址,将指针保存到b中
	fmt.Printf("type of b:%T\n", b)
	c := *b // 指针取值(根据指针去内存取值)
	fmt.Printf("type of c:%T\n", c)
	fmt.Printf("value of c:%v\n", c)
}

取地址操作符&和取值操作符*是一对互补操作符,&取出地址,*根据地址取出地址指向的值。

import "fmt"

func modifyArray(x int) {
	x = 100
}

func modifyArray2(x *int) {
	*x = 100
}

func main() {
	//指针取值
	a := 10
	modifyArray(a)
	fmt.Println(a)//10
	
	modifyArray2(&a)
	fmt.Println(a)//100
	
}

new和make

为什么会有这两个?其实我说实话我也挺懵逼的,看来到哪里都逃不过被new的命运。

在Go语言中对于引用类型的变量,我们在使用的时候不仅要声明它,还要为它分配内存空间,否则我们的值就没办法存储。

如错误例子:

func main() {
	var a *int
	*a = 100
	fmt.Println(*a)

}

在这里插入图片描述
在这里我只做了声明但是没有给他分配内存空间,所以在底层迟迟找不到,然后就报超时。

对于值类型的声明不需要分配内存空间,是因为它们在声明的时候已经默认分配好了内存空间。

所以为了让我们声明的引用类型有内存空间,所以此时我们就需要,引入两个关键字对这种变量分配内存空间。

Go语言中new和make是内建的两个函数,主要用来分配内存。(如果是C语言就需要有释放内存的步骤,但是Go有自动回收的机制)

new

new是一个内置的函数:它的函数签名如下:

func new(Type) *Type

在这里插入图片描述

  • Type表示类型,new函数只接受一个参数,这个参数是一个类型
  • *Type表示类型指针,new函数返回一个指向改类型内存地址的指针。

如何正确使用?

func main() {
	// 声明指针类型
	var a *int
	// 为指针类型分配内空间
	a = new(int)
	// 进行赋值
	*a = 10
	fmt.Println(*a)
}

var a *int只是声明了一个指针变量a但是没有初始化,指针作为引用类型需要初始化后才会拥有内存空间,才可以给它赋值。

总结一下:

  1. 声明指针类型
  2. 为指针类型分配空间
  3. 进行赋值

make

make也是用于内存分配,区别于new,它只是slice,map以及channel的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型本身就是引用类型。所以没有必要去返回一个指针类型了。

make函数是无可替代的,我们在使用slice、map以及channel的时候,都需要使用make进行初始化,然后才可以对它们进行操作。(这三个函数在后续会有讲解)

make的函数签名:

func make(t Type, size ...IntegerType) Type
func main() {
	var b map[string]int
	b = make(map[string]int, 10)
	b["你好"] = 100
	fmt.Println(b)
}

用的还是之前的三板斧

new与make的区别

  1. 二者都是用来分配内存空间的
  2. make只试用slice、map、以及channel的初始话,返回的还是这三个引用类型本身;
  3. new使用于类型的内存分配,并且内存对应的值为类型默认值,返回的是指向类型的指针
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值