• Go出现panic的场景


    概述

    go中发生panic的场景:
    - 数组/切片越界
    - 空指针调用。比如访问一个 nil 结构体指针的成员
    - 过早关闭 HTTP 响应体
    - 除以 0
    - 向已经关闭的 channel 发送消息
    - 重复关闭 channel
    - 关闭未初始化的 channel
    - 未初始化 map。注意访问 map 不存在的 key 不会 panic,而是返回 map 类型对应的零值,但是不能直接赋值
    - 跨协程的 panic 处理
    - sync 计数为负数。
    - 类型断言不匹配。`var a interface{} = 1; fmt.Println(a.(string))` 会 panic,建议用 `s,ok := a.(string)`

    代码

    package a_panics
    
    import (
        "fmt"
        "math/rand"
        "testing"
        "time"
    )
    
    type Student struct {
        Name string
        Age  int
    }
    
    func TestP0(t *testing.T) {
        // 空指针调用: 访问一个 nil 结构体指针的成员
        var s *Student
        fmt.Println(s.Name)
    }
    
    func TestP1(t *testing.T) {
    
        // 除数为0
        fmt.Println(100 / 0)
    
        // rand.Intn方法:如果里面的参数 <=0 的话,会panic
        rand.Seed(time.Now().UnixNano())
        fmt.Println(rand.Intn(0))
    
        // 数组/切片越界
        lst := []string{"whw", "naruto", "sasuke"}
        fmt.Println(lst[0:22])
    
        // 为初始化map
        var m1 map[string]interface{}
        fmt.Println(m1["name"]) // 直接取值不会panic
        m1["age"] = 22
        /*
            // 下面这样可以
            m1 := make(map[string]interface{}, 0)
            m1["age"] = 22
        */
    
        // 断言类型不匹配
        var a interface{} = 1
        fmt.Println(a.(string))
        /*
            // 建议这样写:
            s,ok := a.(string)
            fmt.Println("ok: ", ok, "s: ", s)
        */
    
    }

    ~~~

    package a_panics
    
    import (
        "fmt"
        "io/ioutil"
        "net/http"
        "testing"
    )
    
    func TestHttpBody(t *testing.T) {
    
        url := "https://www.baidu.com"
        method := "GET"
    
        client := &http.Client{}
        req, err := http.NewRequest(method, url, nil)
    
        if err != nil {
            fmt.Println(err)
            return
        }
    
        res, err := client.Do(req)
        if err != nil {
            fmt.Println(err)
            return
        }
    
        // TODO (不加defer)过早关闭HTTP响应体
        defer res.Body.Close()
    
        body, err := ioutil.ReadAll(res.Body)
        if err != nil {
            fmt.Println(err)
            return
        }
        fmt.Println(string(body))
    }

    ~~~

    package a_panics
    
    import "fmt"
    
    import "testing"
    
    func TestChannel0(t *testing.T) {
    
        //ch := make(chan int)
        // 关闭未初始化的channel
        var ch chan int
        close(ch)
    
    }
    
    func TestChannel1(t *testing.T) {
    
        ch := make(chan int) // no-cached channel
        go func() {
            // 子goroutine中向channel中存放值
            ch <- 1
            close(ch)
        }()
        // 主 goroutine 接收channel的值
        x := <-ch
        fmt.Println("x: ", x)
    
        // TODO // 像已关闭的channel发送消息
        ch <- 2
    }
    
    func TestChannel2(t *testing.T) {
    
        ch := make(chan int) // no-cached channel
        go func() {
            // 子goroutine中向channel中存放值
            ch <- 1
            close(ch)
        }()
        // 主 goroutine 接收channel的值
        x := <-ch
        fmt.Println("x: ", x)
    
        // TODO 重复关闭channel
        close(ch)
    }

    ~~~

    package a_panics
    
    import (
        "fmt"
        "testing"
    )
    
    func test(){
    
        defer func(){
            // 捕获异常
            if err := recover(); err != nil{
                fmt.Println("errFromFunc:test", err)
            }
        }()
    
        var m1 map[string]interface{}
        m1["age"] = 22
    }
    
    func sayHello(){
        fmt.Println("hello!")
    }
    
    func TestP4(t *testing.T){
    
        go test()
        go sayHello()
    
    }
  • 相关阅读:
    ZOJ 3818 Pretty Poem
    HDU 4597 Play Game
    HDU 4497 GCD and LCM
    CSU 1335 高桥和低桥
    UVA 10791 Minimum Sum LCM
    CSU 1119 Collecting Coins
    CSU 1120 病毒
    UVA 12169 Disgruntled Judge
    HDU 1301 Jungle Roads
    POJ 1258 Agri-Net
  • 原文地址:https://www.cnblogs.com/paulwhw/p/15585467.html
Copyright © 2020-2023  润新知