声明和定义中的不同函数参数类型

时间:2018-01-26 05:14:42

标签: function go types

在标准库中,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是不同的类型。因为根据golang spec

  

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

  

定义的类型总是与任何其他类型

不同

timerruntimeTimer都是已定义的类型,因此*timer*runtimeTimer是不同的类型。

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

有人可以向我解释一下吗?

由于

1 个答案:

答案 0 :(得分:4)

runtime package function is

2xx

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

  

// go:linkname localname importpath.name

     

// go:linkname指令指示编译器使用“importpath.name”作为源代码中声明为“localname”的变量或函数的目标文件符号名称。由于此指令可以破坏类型系统和包模块化,因此仅在导入“不安全”的文件中启用它。

该指令告诉编译器使用//go:linkname作为此函数的目标文件符号。

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

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