指针和地址的区别
地址:内存地址(用字节来描述的内存地址)
指针:指针是带类型的,int类型指针与string类型指针是完全不同的!指针是存储另一个变量内存地址的变量。
&和*
&:取内存地址
*:根据地址来取值
对变量进行取地址(&)操作,可以获得这个变量的指针变量。
指针变量的值是指针地址。
对指针变量进行取值(*)操作,可以获得指针变量指向的原变量的值。
声明指针
*T是指针变量的类型,指向T类型的指针
var ptr *ptr
指针地址和指针类型
每个变量在运行时都拥有一个地址,这个地址代表变量在内存中的位置。
取变量指针地址:
ptr := &v
v:代表被取地址的变量,类型为T
ptr:用于接收地址的变量,ptr的类型就为T,称做T的指针类型。代表指针。
a := 1
b := &a //取a的内存地址,将指针保存在b中
fmt.Printf("a的值是%d,a的内存地址是%p
",a,&a) //a的值是1,a的内存地址是0xc420080050
fmt.Println(b,*b) //0xc420080050 1
fmt.Printf("%T
",b) //b是int类型的指针 *int
指针取值
指针使用*操作,可以取到指针的值。
fmt.Println(b,*b) //0xc420080050 1
指针传值
func modify1(x int) {
x = 100 //只是修改内部的x的值,值传递
}
//接受的参数是一个指针
func modify2(x *int) {
*x = 100 //传参的时候想要修改传入的参数,需要使用指针,引用传递
}
func main() {
a := 10
modify1(a) //在函数中复制了变量a赋值给了内部的x
fmt.Println(a) //10
modify2(&a)
fmt.Println(a) //100
}
数组指针和指针数组
数组指针:一个指针,一个数组的地址.*[n]type
func main() {
arr1 := [4]int{1, 2, 3, 4}
//创建一个指针,存储该数组的地址--->数组指针
var p1 *[4]int
p1 = &arr1
fmt.Println(p1) //&[1 2 3 4]
fmt.Printf("%p
", p1) //数组arr1的内存地址0xc000092000
fmt.Printf("%p
", &p1) //p1指针的内存地址0xc00008c010
//根据数组指针操作数组
(*p1)[0] = 100
fmt.Println(arr1) //[100 2 3 4]
//简化写法
p1[1] = 200
fmt.Println(arr1) //[100 200 3 4]
}
指针数组:一个数组,存储的数据类型是指针[n]*type
func main() {
//指针数组
a := 1
b := 2
c := 3
d := 4
arr2 := [4]int{a, b, c, d}
arr3 := [4]*int{&a, &b, &c, &d}
fmt.Println(arr2) //[1 2 3 4]
fmt.Println(arr3) //[0xc000016080 0xc000016088 0xc000016090 0xc000016098]
arr2[1] = 100 //修改数组中元素的值
fmt.Println(arr2) //[1 100 3 4]
fmt.Println(b) //2 并没有操作变量的值,所以变量值不变
*arr3[0] = 100
fmt.Println(arr3) //[0xc000016080 0xc000016088 0xc000016090 0xc000016098] 内存地址没有改变
for _, v := range arr3 {
fmt.Println(*v)
}
fmt.Println(a) //100 操作的是变量的内存地址所对应的数据,所以变量值发生改变
}
new()函数创建指针
new()用来做指针的初始化。
语法:
new(T)
EGG:
var a = new(int) //得到一个int类型的指针
fmt.Println(a) //0xc42000e228
*a = 10 //根据内存地址赋值成10
fmt.Println(a) //0xc42000e228
fmt.Println(*a) //10
//值类型的都可以用new初始化,得到一个指针
var b = new([3]int)
fmt.Println(b) //&[0 0 0]
b[0] = 10 //等同于(*b)[0] = 10
fmt.Println(*b) //[10 0 0]