dongxi3911 2018-01-26 05:14
浏览 181
已采纳

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

In the standard library, src/time/sleep.go has the following:

// 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)

The parameter type of startTimer is *runtimeTimer. startTimer implementation is in the src/runtime/time.go, as follows:

// 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)
}

Here the parameter type of startTimer is *timer.

*timer and *runtimeTimer are different types. Because according to golang spec:

Two pointer types are identical if they have identical base types

And

A defined type is always different from any other type

timer and runtimeTimer are both defined types, so *timer and *runtimeTimer are different types.

According to assignability rule, assignment of argumetns in the function call shouldn't work either.

Can anybody explain this to me?

Thanks

  • 写回答

1条回答 默认 最新

  • doucan1979 2018-01-26 05:36
    关注

    The runtime package function is:

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

    The //go:linkname comment is a compiler directive:

    //go:linkname localname importpath.name

    The //go:linkname directive instructs the compiler to use “importpath.name” as the object file symbol name for the variable or function declared as “localname” in the source code. Because this directive can subvert the type system and package modularity, it is only enabled in files that have imported "unsafe".

    This directive tells the compiler to use time.startTimer as the object file symbol for this function.

    The time package function is a declaration only. At link time, the time.startTimer name is bound to the function implemented in the runtime package. This match by name ignores type safety and modularity.

    The purpose of these shenanigans is to allow the time package to call a runtime package function without exporting that function from the runtime package.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 谁能帮我挨个解读这个php语言编的代码什么意思?
  • ¥15 win10权限管理,限制普通用户使用删除功能
  • ¥15 minnio内存占用过大,内存没被回收(Windows环境)
  • ¥65 抖音咸鱼付款链接转码支付宝
  • ¥15 ubuntu22.04上安装ursim-3.15.8.106339遇到的问题
  • ¥15 blast算法(相关搜索:数据库)
  • ¥15 请问有人会紧聚焦相关的matlab知识嘛?
  • ¥15 网络通信安全解决方案
  • ¥50 yalmip+Gurobi
  • ¥20 win10修改放大文本以及缩放与布局后蓝屏无法正常进入桌面