指针在C语言中是很让人头疼的东西,因为其可以进行偏移和运算操作,如果操作不当,很可能会访问到非法、不安全的内存空间,从而导致程序的异常退出
但是在Go语言中,不允许指针进行偏移和运算,是安全指针
Go语言中的指针
任何程序在运行后,在内存中都会有他们的数据,也就是指针
普通变量存的可能是数字或者字符串等等数据
指针变量中存的则是内存地址
go语言中的指针,我们只需要记住两个运算
- 取地址:
&
- 取值:
*
指针地址和指针变量
这一部分内容和C语言中基本相同
func main() {
a := 10
b := &a
fmt.Printf("a:%d ptr:%p\n", a, &a) // a:10 ptr:0xc00001a078
fmt.Printf("b:%p type:%T\n", b, b) // b:0xc00001a078 type:*int
fmt.Println(&b) // 0xc00000e018
}
指针取值
在对普通变量使用&
符号可以得到这个变量对应的指针变量
而对指针变量使用*
符号可以得到对应地址中的内容
内存分配
func main() {
var a *int
*a = 100
fmt.Println(*a)
var b map[string]int
b["沙河娜扎"] = 100
fmt.Println(b)
}
上述代码运行后会触发panic
原因是定义变量时没有进行初始化,也就是没有分配对应的内存空间
而在Go中,要分配内存就要使用make
和new
new
函数原型如下:
func new(Type) *Type
其中,
Type
:表示返回什么类型的指针*Type
:表示分配好的内存指针
对上述代码修改如下,即可正常运行:
func main() {
var a *int
a = new(int)
*a = 10
fmt.Println(*a)
}
make
make和new一样,也是用来进行内存分配的。但相对于new来说,它只用于slice
、map
以及channel
的内存创建,并且返回的类型也是这三个类型本身,而不是其指针类型,函数原型如下:
func make(t Type, size ...IntegerType) Type
对于上述错误代码,修改如下即可正常运行:
func main() {
var b map[string]int
b = make(map[string]int, 10)
b["沙河娜扎"] = 100
fmt.Println(b)
}
new和make的区别
- 二者都是用来做内存分配的。
- make只用于slice、map以及channel的初始化,返回的还是这三个引用类型本身;
- 而new用于类型的内存分配,并且内存对应的值为类型零值,返回的是指向类型的指针。