09-Go语言之指针和异常处理

内容目录

  • 指针

内容详细

指针pointer

  • 普通变量存储的是对应类型的值,这些类型叫值类型

  • 指针也是一个变量,用于存储另一个变量的内存地址,变量存的是值,指针存的是一个地址,这个地址指向的空间存的才是值,所以指针又叫引用类型

  • 与变量类似,使用前需要声明

  • 声明指针并使用:指针取值时变量前面要加星号

  • 注意:不同类型的指针不能互相赋值,所以指针只能读,不能操作指针

    var 指针变量名 *指针类型
    
    func main() {
    	var a int = 20
    	var ip *int // 声明指针
    	ip = &a	// 指针存的是地址
    	fmt.Printf("a的地址:%x\n",&a)
    	fmt.Printf("ip变量存储的指针地址:%x\n",ip)
        
    	fmt.Printf("ip指向的变量的值:%d\n",*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\n",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)
    	}
    }
    // 错误信息为: 半径不能为负
    
posted @ 2020-02-10 13:15  薛定谔的猫儿  阅读(186)  评论(0编辑  收藏  举报