<11>Golang基础进阶——指针

Golang基础进阶——指针

变量和内存地址

每个变量都有内存地址,可以理解为变量来操作对应的内存,go语言的取地址符是&,放到一个变量前使用就会返回相应变量的内存地址,&符跟指针类型息息相关

func main() {
	var a int = 10
	fmt.Printf("变量地址:%x
", &a)
}

指针类型介绍

指针类型,变量存的是一个地址,这个地址存的才是值

获取指针类型所指向的值,使用 *。示例:

func main(){
	var a int
	var p *int
	// 指针只能存储地址否则报错, &a表示取a的地址存储到p
	p = &a
	// p存储的是a的内存地址,取出a地址指向的值就得需要加*,才能从地址中取值
	fmp.Println(*p)
	fmp.Println(p)
}

值类型和引用类型

  • 值类型:int、float、bool、array、struct、string这些类型都属于值类型,使用这些类型的变量直接指向存在内存中的值,值类型的变量的值存储在栈中。当使用等号=将一个变量的值赋给另一个变量时,如 j = i ,实际上是在内存中将 i 的值进行了拷贝。特点:变量直接存储值,内存通常在栈中分配,栈在函数调用完会被释放
  • 引用类型:特指指针、slice、map、channel这三种预定义类型。引用类型拥有更复杂的存储结构:(1)分配内存 (2)初始化一系列属性等一个引用类型的变量r1存储的是r1的值所在的内存地址(数字),或内存地址中第一个字所在的位置,这个内存地址被称之为指针,这个指针实际上也被存在另外的某一个字中。特点:变量存储的是一个地址,这个地址存储最终的值。内存通常在堆上分配,通过GC回收。
var 指针变量名 *指针类型

示例:

func main() {
	var a int = 20
	var ip *int
	// 指针存地址
	ip = &a
	// %x 以十进制方式表示
	fmt.Printf("a的地址:%x
", &a)
	fmt.Printf("ip变量的值:%x
", ip)
	fmt.Printf("ip指向的变量的值:%d
", *ip)
}

 空指针

当一个指针被定义后没有分配到任何变量时,它的值为 nil

func main() {
	var p *int
	fmt.Println(p)
	fmt.Printf("p的值 %x
", p)
}

值传递和引用传递

示例1:

func swap(a, b *int) {
	fmt.Println(a, b)
	*a, *b = *b, *a
}

func main() {
	a, b := 3, 4
	swap(&a, &b)
	fmt.Println(a, b)
}

示例2:

func swap(a, b *int) (*int, *int) {

	a, b = b, a
	return a, b
}

func main() {
	a, b := 3, 4
	c, d := swap(&a, &b)
	fmt.Println(*c, *d)

	a = *c
	// *d 指向 a,a更改为4,所以*d也更改为4
	b = *d
	fmt.Println(a, b)

}

new()和make()

  • make()用来分配引用类型的内存,例如slice、map、channel并且初始化内存
  • new()用来分配各种类型的内存,但它不会初始化内存,创建之后是一个指针类型
  • make()的用途不同于new(),它只能创建slice、map、channel,并返回类型为T(非指针)的已初始化(非零值)的值

示例:

func main() {
	p := new(int)
	fmt.Println(p)        // 0xc000054080
	fmt.Println(*p)       // 0
	fmt.Printf("%T
", p) // *int

	m := make([]int, 10, 50)
	fmt.Println(m)
}
加油,你们是最棒的!
原文地址:https://www.cnblogs.com/Wshile/p/12793624.html