7

I am reading this post about time.startTimer declaration and definition.

From the answer, time.startTimer is declared in src/time/sleep.go as follows:

func startTimer(*runtimeTimer)

And its definition is in src/runtime/time.go as follows:

func startTimer(t *timer) {
    if raceenabled {
        racerelease(unsafe.Pointer(t))
    }
    addtimer(t)
}

So it seems that you can declare a function in one .go file and implement it in another .go file. I tried the same way, for example, declare a function in a.go and implement it in b.go, but it always failed when go run a.go. Is that the correct way to do so? How can I declare a function that is implemented in another .go file? There is no import in either sleep.go or time.go. How does Go do it?

Thanks

JimB
  • 104,193
  • 13
  • 262
  • 255
password636
  • 981
  • 1
  • 7
  • 18

1 Answers1

11

If you look on the line above the startTimer body, you will see a special directive for the go compiler:

//go:linkname stopTimer time.stopTimer

From the compile command documentation

//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".

JimB
  • 104,193
  • 13
  • 262
  • 255
  • 4
    Also note that all of the pragmas should not be relied on in user code. [As Dave Cheney writes](https://dave.cheney.net/2018/01/08/gos-hidden-pragmas), "Pragmas are not part of the language. They might be implemented the gc compiler, but you will not find them in the spec." The [Compatibility Promise](https://golang.org/doc/go1compat) does not apply to pragmas. – Adrian Jan 25 '18 at 14:59
  • There is a very good explanation of this directive here: https://siadat.github.io/post/golinkname – Iain Duncan Jan 25 '18 at 15:18