Go语言的panic类型

1、数组越界(运行时错误)。

package main
import "fmt"
func main() {
	var s []string
	fmt.Println(s)
	fmt.Println(s[0])
}

运行结果:

[]
panic: runtime error: index out of range

goroutine 1 [running]:
main.main()

index out of range:索引超出范围(数组越界)

2、空指针异常(运行时错误)。

package main
import "fmt"
type Person struct {
	Name string
	Age  int
}
func main() {
	var p *Person
	fmt.Println(p)
	fmt.Println(p.Name)
}

运行结果:

<nil>
panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x10914c8]

goroutine 1 [running]:
main.main()

segmentation violation:内存段异常。

3、类型断言失败(接口转换异常)。

package main
import "fmt"
func main() {
	add(20, 18)
	add(1, "hello")
}
func add(a, b interface{}) {
	i := a.(int)
	j := b.(int)
	fmt.Println(i+j)
}

运行结果:

panic: interface conversion: interface {} is string, not int
38

goroutine 1 [running]:
main.add(0x10a0f60, 0x10d6840, 0x10a1660, 0x10d6b90)

interface conversion: interface {} is string, not int:接口转换,接口是string,不是int。

4、通道为空,通道已关闭

package main
func main() {
	var ch chan int
	close(ch)
}

运行结果:

panic: close of nil channel

goroutine 1 [running]:
main.main()

close of nil channel关闭空的通道。

package main
func main() {
	var ch chan int
	ch = make(chan int,0)
	close(ch)
	ch <- 108
}

运行结果:

panic: send on closed channel

goroutine 1 [running]:
main.main()

send on closed channel:发送给已关闭的通道。

5、死锁,所有线程睡眠(致命错误)

这一条是致命错误,不属于panic,但是跟panic异常一样,会导致程序挂掉。

package main
func main() {
	var ch chan int
	ch = make(chan int)
	ch <- 108
}

运行结果:

fatal error: all goroutines are asleep - deadlock!

goroutine 1 [chan send]:
main.main()

fatal error: all goroutines are asleep - deadlock:指明错误,所有线程睡眠,死锁。

6、给空map赋值

package main

func main() {
	var mm map[string]int
	mm["a"] = 10
}

运行结果

panic: assignment to entry in nil map

goroutine 1 [running]:
main.main()

assignment to entry in nil map:赋值到空的map。

7、致命错误:并发的map写

package main

import (
	"fmt"
	"time"
)

func main() {
	mm := make(map[string]int, 0)
	mm["jack"] = 20
	fmt.Println(mm)
	for i := 0; i < 10; i++ {
		name := fmt.Sprint(i)
		go addMap(mm,name,i)
	}
	time.Sleep(time.Second)
	fmt.Println(mm)
}

func addMap(m map[string]int, name string, age int) map[string]int {
	m[name] = age
	return m
}

运行结果

map[jack:20]
fatal error: concurrent map writes

goroutine 42 [running]:
runtime.throw(0x10c8fe1, 0x15)
	/usr/local/Cellar/go/1.12.1/libexec/src/runtime/panic.go:617 +0x72 fp=0xc0000a6f18 sp=0xc0000a6ee8 pc=0x1027e52
runtime.mapassign_faststr(0x10ab2c0, 0xc000098000, 0x1162919, 0x1, 0x0)
	/usr/local/Cellar/go/1.12.1/libexec/src/runtime/map_faststr.go:211 +0x42a fp=0xc0000a6f80 sp=0xc0000a6f18 pc=0x100fe9a
main.addMap(0xc000098000, 0x1162919, 0x1, 0x9, 0x0)
	/Users/ElonJelinek/go/src/kongyixueyuan.com/prac0424/test09.go:21 +0x4b fp=0xc0000a6fb8 sp=0xc0000a6f80 pc=0x1093c0b
runtime.goexit()

concurrent map writes:并发map写。
Go语言中,map只能并发的读,不可以并发的写,如果要在多个线程中对map进行写操作,必须要加锁

8、递归死循环,堆栈溢出(运行时:goroutine堆栈超出限制,致命错误:堆栈溢出)

package main

import "fmt"

type People1 struct {
	Name string
}

func (p *People1) String() string {
	return fmt.Sprintf("print: %v", p)
}

func main() {
	p := &People1{"杰克"}
	s := p.String()
	fmt.Println(s)
}

运行结果

runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow

runtime stack:
runtime.throw(0x10c8f32, 0xe)
	/usr/local/Cellar/go/1.12.1/libexec/src/runtime/panic.go:617 +0x72
runtime.newstack()
	/usr/local/Cellar/go/1.12.1/libexec/src/runtime/stack.go:1041 +0x6f0
runtime.morestack()
	/usr/local/Cellar/go/1.12.1/libexec/src/runtime/asm_amd64.s:429 +0x8f

goroutine 1 [running]:
runtime.heapBitsSetType(0xc013a67380, 0xc0, 0xb8, 0x10bdce0)
	/usr/local/Cellar/go/1.12.1/libexec/src/runtime/mbitmap.go:938 +0xa56 fp=0xc024000330 sp=0xc024000328 pc=0x1012b96
runtime.mallocgc(0xc0, 0x10bdce0, 0x1, 0x0)

这里出现了递归循环调用,即死循环,因为结构体people重写了官方包的String()方法,而fmt.Sprintf()中调用了String()方法,就出现了又回到p.String()方法,然后又调用fmt.Sprintf()方法,然后又回来,导致死循环,也导致堆栈溢出。

runtime: goroutine stack exceeds 1000000000-byte limit:运行时:goroutine堆栈超出1000000000字节限制
fatal error: stack overflow
致命错误:堆栈溢出

这种错误在递归没有出口的时候出现,也就是递归死循环的时候出现

package main

import "fmt"

func main() {
	n := fibonacci(5)
	fmt.Println(n)
}

func fibonacci(n int) int {
	//if n <= 1 {
	//	return n
	//}
	return fibonacci(n-1) + fibonacci(n-2)
}

运行结果

runtime: goroutine stack exceeds 1000000000-byte limit
fatal error: stack overflow

runtime stack:
runtime.throw(0x10c71e3, 0xe)

map并发加锁

package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
	mut := new(sync.Mutex)
	mm := make(map[string]int, 0)
	mm["jack"] = 20
	fmt.Println(mm)
	for i := 0; i < 20; i++ {
		name := fmt.Sprint(i)
		go addMap(mm,name,i,mut)
	}
	time.Sleep(time.Second)
	fmt.Println(mm)
}

func addMap(m map[string]int, name string, age int,mu *sync.Mutex) map[string]int {
	mu.Lock()
	m[name] = age
	mu.Unlock()
	return m
}

猜你喜欢

转载自blog.csdn.net/Charliewolf/article/details/88230502