一、指针

go语言中的指针非常重要,非常重要,非常重要。

了解指针需要先知道3个概念:指针地址、指针类型和指针取值。

指针地址和指针类型  

每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。Go语言中使用&字符放在变量前面对变量进行“取地址”操作。 Go语言中的值类型(int、float、bool、string、array、struct)都有对应的指针类型,如:*int*int64*string等。

取变量指针的语法如下:

ptr := &v    // v的类型为T

其中:

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

指针取值        

func main() {
	//指针取值
	a := 10
    // 取变量a的地址,将指针保存到b中
	b := &a 
	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)
}

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

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

  • 对变量进行取地址(&)操作,可以获得这个变量的指针变量。
  • 指针变量的值是指针地址。
  • 对指针变量进行取值(*)操作,可以获得指针变量指向的原变量的值。

二、实战

package main

import "fmt"

/**
指针


 */
func main() {
	// 定义整形变量a
	a :=10

	// 变量b 是一个int 类型的指针(*int) 他存储的是变量a的内存地址
	b :=&a

	//10 0xc000014058
	fmt.Printf("%v %p\n",a,&a)

	//0xc000014058 0xc000014058
	fmt.Printf("%v %p\n",b,b)

	//根据内存地址取变量
	c :=*b

	fmt.Println("c value=",c)

}
package main

import "fmt"

/**
指针修改参数

我们只需要记住两个符号:&(取地址)和*(根据地址取值)。
 */
func main() {

	a :=1
	modify1(a)

	fmt.Println("a==",a)

	modify2(&a)

	fmt.Println("a通过地址赋值后的参数",a)

}

func modify1(x int) {
	x = 100
}


func modify2(y *int) {

	*y = 100

}

new与make的区别: 1、二者都是用来做内存分配的。 2、make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身; 3、而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。

package main

import "fmt"
/**

new与make的区别:

1、二者都是用来做内存分配的。
2、make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身;
3、而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。

 */
func main() {

	// new 函数
	var a  *int

	a =new(int)

	fmt.Println(*a)

	*a =100

	fmt.Println(*a)


	// make 函数
	var b map[string] int

	b = make(map[string]int,10)
	b["测试"] = 200

	fmt.Println("b==",b)

}

什么时候应该使用指针类型接收者
1、需要修改接收者中的值
2、接收者是拷贝代价比较大的大对象
3、保证一致性,如果有某个方法使用了指针接收者,那么其他的方法也应该使用指针接收者。
 

package main

import "fmt"

/**
方法的定义和接收者

 */
func main() {

	user1 :=NewUser("tom",int8(9))

	user1.Speak()

	fmt.Println("user1=",user1)

	(*user1).Speak()

	fmt.Println("user2=",user1)


}


// User 是一个对外暴露的结构体
type User struct {

	name string

	age int8
}


// 构造函数
func NewUser(name string,age int8) *User {

	return &User{
		name:"tom",
		age:1,

	}
}

// 给User 定义方法
func (u User)Speak()  {
	fmt.Println("说出了什么?",u.name)
}