一、指针
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)
}