天天看点

Go的异常退出场景1.因为数组/切片索引越界2.空指针调用3.过早关闭http响应体4.除以零5.向已经关闭的通道发送信息6.重复关闭通道7.关闭未初始化的通道8.未初始化 map9.跨协程的“恐慌”处理10.sync计数为负值

go程序异常painc 退出的场景

引用书籍《Go语言编程之旅》

1.因为数组/切片索引越界

package main

import "fmt"

func main() {
	names := []string{
		"test",
		"test2",
	}
	name := names[len(names)]
	fmt.Println(name)

}
           
Go的异常退出场景1.因为数组/切片索引越界2.空指针调用3.过早关闭http响应体4.除以零5.向已经关闭的通道发送信息6.重复关闭通道7.关闭未初始化的通道8.未初始化 map9.跨协程的“恐慌”处理10.sync计数为负值

2.空指针调用

package main

import "fmt"

type User struct {
	name string
}

func (u *User) GetName() string {
	return  u.name
}
func main() {
	s := &User{}
	s = nil
	name := s.GetName()
	fmt.Println(name)


}
           
Go的异常退出场景1.因为数组/切片索引越界2.空指针调用3.过早关闭http响应体4.除以零5.向已经关闭的通道发送信息6.重复关闭通道7.关闭未初始化的通道8.未初始化 map9.跨协程的“恐慌”处理10.sync计数为负值

3.过早关闭http响应体

package main

import (
	"log"
	"net/http"
)

func main() {
	resp,err := http.Get("baidu.com")
	//1
	defer resp.Body.Close()
	if err != nil {
		log.Fatalf("http get err is : %s \n",err)
	}
	//2
	defer resp.Body.Close()

}
           

当defer在1的时候

Go的异常退出场景1.因为数组/切片索引越界2.空指针调用3.过早关闭http响应体4.除以零5.向已经关闭的通道发送信息6.重复关闭通道7.关闭未初始化的通道8.未初始化 map9.跨协程的“恐慌”处理10.sync计数为负值

当defer在2的时候

Go的异常退出场景1.因为数组/切片索引越界2.空指针调用3.过早关闭http响应体4.除以零5.向已经关闭的通道发送信息6.重复关闭通道7.关闭未初始化的通道8.未初始化 map9.跨协程的“恐慌”处理10.sync计数为负值

所以我们在做defer的时候一定要先做错误判断 在做完了错误判断之后我们才可以做defer 包括mysql的 db.close

4.除以零

package main

func D(a,b int) int{
	return a/b
}

func main() {
	D(1,0)
}
           
Go的异常退出场景1.因为数组/切片索引越界2.空指针调用3.过早关闭http响应体4.除以零5.向已经关闭的通道发送信息6.重复关闭通道7.关闭未初始化的通道8.未初始化 map9.跨协程的“恐慌”处理10.sync计数为负值

5.向已经关闭的通道发送信息

package main

func main() {
	ch := make(chan int,1)
	ch <- 1
	close(ch)
	ch <- 2
}
           
Go的异常退出场景1.因为数组/切片索引越界2.空指针调用3.过早关闭http响应体4.除以零5.向已经关闭的通道发送信息6.重复关闭通道7.关闭未初始化的通道8.未初始化 map9.跨协程的“恐慌”处理10.sync计数为负值

6.重复关闭通道

package main

func main() {
	ch := make(chan int,1)
	ch <- 1
	close(ch)
	close(ch)
}
           
Go的异常退出场景1.因为数组/切片索引越界2.空指针调用3.过早关闭http响应体4.除以零5.向已经关闭的通道发送信息6.重复关闭通道7.关闭未初始化的通道8.未初始化 map9.跨协程的“恐慌”处理10.sync计数为负值

7.关闭未初始化的通道

package main

func main() {
	var ch chan  int
	close(ch)
}
           
Go的异常退出场景1.因为数组/切片索引越界2.空指针调用3.过早关闭http响应体4.除以零5.向已经关闭的通道发送信息6.重复关闭通道7.关闭未初始化的通道8.未初始化 map9.跨协程的“恐慌”处理10.sync计数为负值

8.未初始化 map

package main

func main() {
	var user map[string]int
	user["test"] = 1
}
           
Go的异常退出场景1.因为数组/切片索引越界2.空指针调用3.过早关闭http响应体4.除以零5.向已经关闭的通道发送信息6.重复关闭通道7.关闭未初始化的通道8.未初始化 map9.跨协程的“恐慌”处理10.sync计数为负值

9.跨协程的“恐慌”处理

package main

import (
	"log"
	"time"
)

func main() {
	go func() {
		defer func() {
			if err := recover();err != nil {
				log.Fatalf("recover is err %v \n",err)
			}
		}()
		handler()
	}()
	time.Sleep(time.Second)
}

func handler() {
	go divide(1,0)
}
func divide(a,b int) int {
	return  a/b
}
           
Go的异常退出场景1.因为数组/切片索引越界2.空指针调用3.过早关闭http响应体4.除以零5.向已经关闭的通道发送信息6.重复关闭通道7.关闭未初始化的通道8.未初始化 map9.跨协程的“恐慌”处理10.sync计数为负值

10.sync计数为负值

package main

import "sync"

func main() {
	wg := sync.WaitGroup{}
	wg.Done()
	wg.Wait()
}
           
Go的异常退出场景1.因为数组/切片索引越界2.空指针调用3.过早关闭http响应体4.除以零5.向已经关闭的通道发送信息6.重复关闭通道7.关闭未初始化的通道8.未初始化 map9.跨协程的“恐慌”处理10.sync计数为负值