Go 1.21的2個語言變化

coding進階發表於2023-02-18

語言行為變化

Go 1.20已經於今年2月份釋出,Go 1.21也不遠了,我們來先睹為快,看看Go 1.21版本里幾個有趣的變化。

文末附送2道面試題。

panic(nil)

func main() {
  defer func() {
    print(recover() == nil)
  }()
  panic(nil)
}

大家先想一想這段程式碼會輸出什麼?是true還是false。

在Go 1.20版本及以前會輸出true。

但是在Go 1.21版本開始會輸出false。這是因為Go 1.21定義了一個新的型別*runtime.PanicNilError

panic(nil)後,recover()會返回一個型別為*runtime.PanicNilError,值為panic called with nil argument的變數,具體可以參考如下程式碼:

func main() {
    defer func() {
        r := recover()
        fmt.Printf("%T\n", r) // *runtime.PanicNilError
        fmt.Println(r) // panic called with nil argument
    }()
    panic(nil)
}

clear函式

Go 1.21會新增一個clear函式,用於清理map和slice裡的元素。示例程式碼如下:

package main

import "fmt"

var x = 0.0
var nan = x / x

func main() {
    s := []int{1, 2, 3}
    clear(s)
    fmt.Println(s) // [0 0 0]

    m := map[float64]int{0.1: 9}
    m[nan] = 5
    clear(m)
    fmt.Println(len(m)) // 0
}

官方原始碼說明如下:

// The clear built-in function clears maps and slices.

// For maps, clear deletes all entries, resulting in an empty map.

// For slices, clear sets all elements up to the length of the slice

// to the zero value of the respective element type. If the argument

// type is a type parameter, the type parameter's type set must

// contain only map or slice types, and clear performs the operation

// implied by the type argument.

func clear[T ~[]Type | ~map[Type]Type1](t T "T ~[]Type | ~map[Type]Type1")

對於map,呼叫clear函式,會直接把map裡的元素清空,成為一個empty map。

對於slice,呼叫clear函式,會保持原slice的長度不變,把裡面元素的值修改為slice元素型別的零值。

面試題

defer語義是Go開發人員經常使用到的,也是最容易理解錯誤的地方。

大家看看下面2道關於defer的程式會輸出什麼結果。

package main

import "fmt"

func f() {
    defer func() {
        defer func() { recover() }()
        defer recover()
        panic(2)
    }()
    panic(1)
}

func main() {
    defer func() { fmt.Print(recover()) }()
    f()
}
  • A: 2
  • B: 1
  • C: nil
  • D: 拋panic異常
package main

import "fmt"

func main() {
    for i := 0; i < 3; i++ {
        defer func() { print(i) }()
    }
    for i := range [3]int{} {
        defer func() { print(i) }()
    }
}
  • A: 222333
  • B: 210333
  • C: 333333
  • D: 210210

想知道答案的傳送訊息121到公眾號。

推薦閱讀

開源地址

文章和示例程式碼開源在GitHub: Go語言初級、中級和高階教程

公眾號:coding進階。關注公眾號可以獲取最新Go面試題和技術棧。

個人網站:Jincheng's Blog

知乎:無忌

福利

我為大家整理了一份後端開發學習資料禮包,包含程式語言入門到進階知識(Go、C++、Python)、後端開發技術棧、面試題等。

關注公眾號「coding進階」,傳送訊息 backend 領取資料禮包,這份資料會不定期更新,加入我覺得有價值的資料。還可以傳送訊息「進群」,和同行一起交流學習,答疑解惑。

References

相關文章