为什么在 unsafe.Sizeof() 中取消引用 nil 指针不会导致恐慌?

Why doesn't dereferencing a nil pointer in unsafe.Sizeof() cause a panic?

https://go.dev/play/p/X_BH4qGgXHJ

package main

import (
    "fmt"
    "unsafe"
)

func main() {
    var i *int
    fmt.Println(unsafe.Sizeof(*i)) // dereference of null pointer i
}

为什么这段代码没有

unsafe.Sizeof(*i)

导致运行时恐慌?

Spec: Package unsafe:

Calls to Alignof, Offsetof, and Sizeof are compile-time constant expressions of type uintptr.

这些函数在编译时求值,在运行时不会发生实际的解除引用。

这是可能的,因为不需要指向的值,只需要有关其类型的信息,不需要取消引用。

它也记录在 unsafe.Sizeof():

The return value of Sizeof is a Go constant.

Go 中的常量是 compile-time 个常量。

另见 Spec: Constants:

A constant value is represented by a rune, integer, floating-point, imaginary, or string literal, an identifier denoting a constant, a constant expression, a conversion with a result that is a constant, or the result value of some built-in functions such as unsafe.Sizeof applied to any value, cap or len applied to some expressions, real and imag applied to a complex constant and complex applied to numeric constants.

查看类似的示例(如果不将它们传递给 unsafe.Sizeof() 会在运行时恐慌或无限期阻塞,但它们工作得很好):

fmt.Println(unsafe.Sizeof(*(*int8)(nil))) // 1, no dereferencing
fmt.Println(unsafe.Sizeof([]int16{}[10])) // 2, no indexing
x := "hi"
fmt.Println(unsafe.Sizeof(x[10]))                          // 1, no indexing
fmt.Println(unsafe.Sizeof(map[interface{}]int{}[[]int{}])) // 8, no indexing
fmt.Println(unsafe.Sizeof((interface{})(nil).(int16)))     // 2, no type assertion
i := 0
fmt.Println(unsafe.Sizeof(i / i)) // 8, no division by 0
i = -1
fmt.Println(unsafe.Sizeof(1 << i))                // 8, no negative shift count
fmt.Println(unsafe.Sizeof(make([]int, i)))        // 24, no negative length
fmt.Println(unsafe.Sizeof((*[1]int)([]int{})))    // 8, no converting to bigger array
fmt.Println(unsafe.Sizeof((func() int32)(nil)())) // 4, no function call
fmt.Println(unsafe.Sizeof(<-(chan int64)(nil)))   // 8, no receiving
var a, b interface{} = []int{}, []int{}
fmt.Println(unsafe.Sizeof(a == b)) // 1, no comparison

Go Playground 上试试这些。