概念
任何程序数据载入内存后,在内存都有他们的地址,这就是指针。而为了保存一个数据在内存中的地址,我们就需要指针变量。
指针地址和指针类型
取变量指针
v := name
ptr := &name
-
name
:表示被取出的变量。类型为:string
-
ptr
:用于接收地址的变量,类型为*string
,称为string
的指针类型。*
代表指针。
package main
import "fmt"
func main(){
name := "jack"
ptr := &name
// 通过 & 去可以取变量在内存中的地址
fmt.Printf("%p\n",&name) //0xc0000421f0
fmt.Println(ptr) //0xc0000421f0
}
指针取值
package main
import "fmt"
func main(){
name := "jack"
ptr := &name
// 通过 & 去可以取变量在内存中的地址
fmt.Printf("%p\n",&name) //0xc0000421f0
fmt.Println(ptr) //0xc0000421f0
// 对地址变量取址
fmt.Println(&ptr) //0xc000006028
// 指针取值
fmt.Println(*ptr) // jack
}
取地址操作符
&
和取值操作符*
是一对互补操作符,&
取出地址,*
根据地址取出内存中对应的值。
- 对变量进行取地址(&)操作,可以获得这个变量的指针变量。
- 指针变量的值是指针的地址。
- 对指针变量进行取值(*)操作,可以获取指针变量指向的原变量的值。
指针传值示例
package main
import "fmt"
func f1(x int){
x = 123
}
func f2(x *int){
*x = 321
}
func main(){
// 传的是复制的值,两个值是存在不同的内存中
a := 1
f1(a)
fmt.Println(a) //1
//传的是变量的地址,指向同一块内存
f2(&a)
fmt.Println(a) //321
}
分配内存的函数
new
package main
import "fmt"
func main() {
// new函数的签名
func new(Type) *Type
// Type:表示类型,*Type:表示类型指针
// 使用new函数是一个类型的指针
a := new(int)
b := new(string)
fmt.Printf("%T\n", a) // *int
fmt.Printf("%T\n", b) //*string
fmt.Printf("%v\n", a) //0xc000070068
fmt.Printf("%v\n", *a) // 0
fmt.Printf("%v\n", b) //0xc0000581e0
fmt.Printf("%v\n", *b) // ''
// 变量的定义
var p *int
// *p = 123
// panic: runtime error: invalid memory address or nil pointer dereference
// 变量的初始化
p = new(int)
*p = 123
fmt.Println(*p) // 123
}
make
make也是用于内存分配的,区别于new,它只用于slice、map以及chan的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没有必要返回他们的指针了
package main
import "fmt"
func main(){
// make函数的签名
func make(t Type, size ...IntegerType) Type
var b map[string]int
b = make(map[string]int, 10)
b["沙河娜扎"] = 100
fmt.Println(b)
}
make和new的区别
- 二者都是用来做内存分配的
- make只用于
slice
、map
以及channel
的初始化,返回的还是这三个引用类型的本身。 - 而new用于类型的内存分配,并且内存对应的值为类型零型,返回的是指针类型的指针。