内容目录
- 指针
内容详细
指针pointer
-
普通变量存储的是对应类型的值,这些类型叫值类型
-
指针也是一个变量,用于存储另一个变量的内存地址,变量存的是值,指针存的是一个地址,这个地址指向的空间存的才是值,所以指针又叫引用类型
-
与变量类似,使用前需要声明
-
声明指针并使用:指针取值时变量前面要加星号
-
注意:不同类型的指针不能互相赋值,所以指针只能读,不能操作指针
var 指针变量名 *指针类型 func main() { var a int = 20 var ip *int // 声明指针 ip = &a // 指针存的是地址 fmt.Printf("a的地址:%x ",&a) fmt.Printf("ip变量存储的指针地址:%x ",ip) fmt.Printf("ip指向的变量的值:%d ",*ip) // 指针取值加星号 } // a的地址:c000010090 // ip变量存储的指针地址:c000010090 // ip指向的变量的值:20
-
指针和地址什么区别?
- 地址:就是内存地址(用字节来描述的内存地址)
- 指针:指针是带类型的
-
&
和*
只有两个符号&
:表示取地址*
:根据地址取值
指针可以修改数组
// 接收的参数是一个数组的指针
func modifyArray(a1 *[3]int){
(*a1)[0] = 100 // 修改指针内部的值
a1[1] = 200 // 语法糖也可以这样写
}
func main() {
a := [3]int{1,2,3}
modifyArray(&a) //把a以指针形式传参进修改的函数
fmt.Println(a)
}
空指针
-
当一个指针被定义后没有分配到任何变量时,它的值为nil
-
空指针的判断
func main() { var p *int fmt.Println(p) fmt.Printf("p的值 %x ",p) // 空指针进行判断 if p!=nil { fmt.Println("非空") }else { fmt.Println("空") } } // <nil> // p的值 0 // 空
值传递和引用传递
值类型
var a int // 0
var b string //
var c float32 // 0
var e bool // false
引用类型
-
make()是给引用类型申请内存空间的
var x []int // nil var m map[string]int // nil
new和make
-
new是用来初始化值类型指针的
func main() { // var a *int 声明a是一个int类型的指针 // 以上是错误的写法,因为声明后不能初始化,a只能是空指针 var a = new(int) // 得到一个int类型的指针 fmt.Println(a) *a = 10 // 赋值给a的值 fmt.Println(a) fmt.Println(*a) var c = new([3]int) // 得到一个3长度的int类型数组指针 fmt.Println(c) c[0] = 1 // 赋值给第一个元素 fmt.Println(*c) } /* 0xc000010090 0xc000010090 10 &[0 0 0] [1 0 0] */
-
make只是用来初始化slice、map、chan的内存创建,而且它返回的类型就是这三个类型本身,而不是他们的指针类型,因为这三种类型就是引用类型,所以就没必要返回他们的指针了。
panic和recover
-
panic
是抛出异常 -
recover
是捕获异常,必须与defer
配合才能使用 -
注意:
defer
一定要在可能引发panic
的语句之前定义。func f1(){ defer func() { // recover err := recover() // 尝试将函数从当前的异常状态恢复过来 fmt.Println("recover捕获到了panic异常", err) }() var a[]int a[0] = 100 // 此时会报出panic错误 fmt.Println("panic之后") } func main() { f1() fmt.Println("这是main函数") } // recover捕获到了panic异常 runtime error: index out of range [0] with length 0 // 这是main函数
-
示例:
func getCircleArea(radius float32) (area float32) { if radius < 0 { // 程序自己抛出异常 panic("半径不能为负数") } return 3.14 * radius * radius } func test(){ // 延时执行匿名函数 // 延时到何时?(1)程序正常结束 (2)程序发生异常 defer func() { // recover()会返回程序为什么挂了 if err := recover();err !=nil{ fmt.Println(err) } }() getCircleArea(-5) fmt.Println("如果上一步程序错误,程序执行不到这里") } func test01(){ test() fmt.Println("正常运行test01")// 程序在test出现异常后,照样会执行这一句,不会影响此函数中的执行代码 } func main() { test01() } // 半径不能为负数 // 正常运行test01
error类型:自定义错误后输出信息
-
error可以作为函数的返回值,是数据类型的一种
// 函数返回值为error类型 func getCircleArea(radius float32) (area float32, err error) { if radius < 0 { // 程序自己抛出异常,然后自定定义异常输出的信息 err = errors.New("半径不能为负") } area = 3.14 * radius * radius return } func main() { area, err := getCircleArea(-5) // 处理异常: if err != nil { fmt.Println("错误信息为:", err) } else { fmt.Println("园的面积为:", area) } } // 错误信息为: 半径不能为负