在标准库中,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
的参数类型为*runtimeTimer
。 startTimer
的实施位于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:
如果两种指针类型具有相同的基本类型,则它们是相同的
和
定义的类型总是与任何其他类型
不同
timer
和runtimeTimer
都是已定义的类型,因此*timer
和*runtimeTimer
是不同的类型。
根据可转让性rule,函数调用中的参与者的分配也不应该起作用。
有人可以向我解释一下吗?
由于
答案 0 :(得分:4)
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名称绑定到运行时包中实现的函数。这种名称匹配忽略了类型安全性和模块性。
这些恶作剧的目的是允许时间包调用运行时包函数而不从运行时包中导出该函数。