Go语言基础之指针

1 指针

1.1 Go语言中指针介绍

指针是程序载入到内存中的所对应的地址,为了保存数据在内存中对应的地址,就有了指针变量。指针在内存中的示意图如下:

Go语言中的指针不能进行偏移和运算,是安全指针。在Golang中只有&(取址)和*(取值)两个操作。

1.2 指针和地址的区别

地址:是内存地址(用字节来描述的内存地址)

指针:指针存储执行类型数据在内存空间中对应的地址。比如说string类型的指针,其只能存储string变量类型的指针

1.3 指针和指针类型

如同上面所说,指针是地址,但是地址不是指针,因为指针有其对应的类型,如*intfloat64*string等。

取变量指针的语法如下:

ptr := &v	// v的类型为T
  • v:代表被取地址的变量,类型为T
  • ptr:用于接收地址的变量,ptr的类型就是*T,称其为T的指针类型

代码演示:

func main()  {
	var a int
	fmt.Println(a)		//0
	b := &a  // 取变量a的内存地址
	fmt.Printf("b=%v\n", b)			//b=0xc00000a0c0
	fmt.Printf("type b:%T\n", b)	//type b:*int

	c := "tom"
	// b = &c  //go语言是静态类型,变量只能存储一种类型的地址
	// golang中的地址只能读不能操作
	fmt.Printf("&c=%v\n", &c)	//&c=0xc0000321f0

	d := 100
	b = &d
	fmt.Println(b)		//0xc00000a0d8
	// *取地址对应的值
	fmt.Println(*b)		//100
	// 指针可以做逻辑判断
	fmt.Println(b == &d)	//true
}

对于上述代码的说明:

  • b := &a在内存中的示意图:

  • 语法糖:因为go语言中的指针不支持地址的修改,所以编译器会默认修改指针对应的值。也就是说,如果有一个指针类型的变量ptr,对其进行一些运算(加法运算),在使用的过程中*ptr + 2等价于ptr + 2

1.4 指针的使用场景

指针通常会在函数之间的传参时使用。函数在传参时是通过值传参的,比如参数是数组,在传参的过程中形参会对实参的值拷贝一份存储在形参变量中,如果这个数组很大时,那么这个过程就很浪费内存,这时就可以使用指针进行传参,不论数组有多大,传参过程中所耗费的内存空间都是固定的。

指针传值示例:

func modify1(x int) {
	x = 100
}

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

func main() {
	a := 10
	modify1(a)
	fmt.Println(a) // 10
	modify2(&a)
	fmt.Println(a) // 100
}

2 new和make

在Go语言中对于值类型的声明不需要分配内存空间,因为它们在声明的时候已经默认分配好了内存空间;而对于引用类型的以下变量,不仅要声明它,还需对其进行内存空间的分配,比如:

var a *int的意思是a是一个int类型的指针,但是在内存中没有其存放的地方,应当声明其存放的地址,以及该地址对应的值(初始化)。

Golang中的newmake都是内建函数,主要用来分配内存。

2.1 new

new函数主要给一些值类型(int系列,数组)的指针分配内存空间,其函数签名如下:

func new(Type) *Type

其中,

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

new函数不太常用,使用new函数得到的是一个值类型的指针,并且该指针对应的值为该类型的零值。如下示例:

func main() {
	a := new(int)
	b := new(bool)
	fmt.Printf("%T\n", a) // *int
	fmt.Printf("%T\n", b) // *bool
	fmt.Println(*a)       // 0
	fmt.Println(*b)       // false
}

在声明了一个指针变量后,需要对其进行初始化。按照如下方式使用new函数对a进行初始化以及赋值操作:

func main() {
	var a *int
	a = new(int)
	*a = 10
	fmt.Println(*a)
}

2.2 make

make函数主要给一些引用类型(slice,map,channel)进行初始化,该函数返回的类型就是引用类型本身,而不是指针类型。因为其本身就是引用类型,所以就没有必要返回指针。

make的函数签名如下:

func make(t Type, size ...IntegerType) Type

make函数使用示例:

func main() {
	var b map[string]int	//声明了一个map类型的变量b
	b = make(map[string]int, 10)	//开辟存储长度为10的map类型
	b["age"] = 20
	fmt.Println(b)
}

2.3 new和make的区别

  • 二者都是用来做内存的分配
  • make用于对引用类型的初始化,返回的是引用类型的本身
  • new用于值类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针
posted @ 2020-02-23 10:09  Dabric  阅读(279)  评论(0编辑  收藏  举报
TOP