【问题标题】:Different function parameter types in declaration and definition声明和定义中不同的函数参数类型
【发布时间】:2018-07-05 11:37:41
【问题描述】:

在标准库中,src/time/sleep.go 有以下内容:

// Interface to timers implemented in package runtime.
// Must be in sync with ../runtime/runtime.h:/^struct.Timer$
type runtimeTimer struct {
    i      int
    when   int64
    period int64
    f      func(interface{}, uintptr) // NOTE: must not be closure
    arg    interface{}
    seq    uintptr
}

func startTimer(*runtimeTimer)

startTimer的参数类型为*runtimeTimerstartTimer实现在src/runtime/time.go中,如下:

// Package time knows the layout of this structure.
// If this struct changes, adjust ../time/sleep.go:/runtimeTimer.
// For GOOS=nacl, package syscall knows the layout of this structure.
// If this struct changes, adjust ../syscall/net_nacl.go:/runtimeTimer.
type timer struct {
    i int // heap index

    // Timer wakes up at when, and then at when+period, ... (period > 0 only)
    // each time calling f(arg, now) in the timer goroutine, so f must be
    // a well-behaved function and not block.
    when   int64
    period int64
    f      func(interface{}, uintptr)
    arg    interface{}
    seq    uintptr
}

// startTimer adds t to the timer heap.
//go:linkname startTimer time.startTimer
func startTimer(t *timer) {
    if raceenabled {
        racerelease(unsafe.Pointer(t))
    }
    addtimer(t)
}

这里startTimer的参数类型是*timer

*timer*runtimeTimer 是不同的类型。因为根据golangspec

如果两个指针类型具有相同的基类型,则它们是相同的

定义的类型总是不同于任何其他类型

timerruntimeTimer 都是定义类型,所以 *timer*runtimeTimer 是不同的类型。

根据可分配性rule,函数调用中的参数分配也不应该起作用。

谁能给我解释一下?

谢谢

【问题讨论】:

    标签: function go types


    【解决方案1】:

    runtime package function is

    //go:linkname startTimer time.startTimer
    func startTimer(t *timer) {
        if raceenabled {
            racerelease(unsafe.Pointer(t))
        }
        addtimer(t)
    }
    

    //go:linkname 评论是compiler directive

    //go:linkname localname importpath.name

    //go:linkname 指令指示编译器使用“importpath.name”作为源代码中声明为“localname”的变量或函数的目标文件符号名称。因为这个指令可以颠覆类型系统和包的模块化,所以它只在导入了“unsafe”的文件中启用。

    这个指令告诉编译器使用time.startTimer作为这个函数的目标文件符号。

    time package function 只是一个声明。在链接时,time.startTimer 名称绑定到运行时包中实现的函数。这种名称匹配忽略了类型安全和模块化。

    这些恶作剧的目的是允许 time 包调用运行时包函数,而无需从运行时包中导出该函数。

    【讨论】:

    • “这个按名称匹配忽略了类型安全和模块化”,所以time.startTimer的参数类型我可以使用任何类型,只要函数名称相同即可。例如,我什至可以使用这个:func startTimer()func startTimer(int),对吧?
    • 程序将使用func startTimer()func startTimer(int) 构建,但不能保证程序会在没有段错误的情况下执行调用。
    猜你喜欢
    • 1970-01-01
    • 2021-03-23
    • 1970-01-01
    • 1970-01-01
    • 2021-05-30
    • 1970-01-01
    • 2012-02-16
    • 1970-01-01
    相关资源
    最近更新 更多