Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

spec: add __FILE__ and __LINE__ macro #12876

Closed
j16sdiz opened this issue Oct 8, 2015 · 7 comments
Closed

spec: add __FILE__ and __LINE__ macro #12876

j16sdiz opened this issue Oct 8, 2015 · 7 comments

Comments

@j16sdiz
Copy link

j16sdiz commented Oct 8, 2015

The current Caller() method is more flexible, but it encourage hardcoded stack depth constant (see https://golang.org/src/log/log.go#173 ). This is easy to bitrot.

Constant (or marco) like __FILE__ push the responsibility to the caller. Maybe a little bit hard to use, but it is simpler to maintain.

Reference: https://groups.google.com/d/msg/golang-nuts/3_UFKPKIzRU/HKCC8KqOhQYJ

@adg adg changed the title Add __FILE__ and __LINE__ macro log: add __FILE__ and __LINE__ macro Oct 8, 2015
@ianlancetaylor ianlancetaylor added this to the Unplanned milestone Oct 8, 2015
@minux
Copy link
Member

minux commented Oct 8, 2015

Go doesn't have anything like this before, so I'd hesitate
to introduce these.

Also FILE and LINE look quite ugly in Go.

The reference you cited is a few years old, and I'm wondering
if @ianlancetaylor still thinks we might want to add these to
Go?

@griesemer
Copy link
Contributor

I can see the use for access to what are constants known to the compiler, and it's not entirely unprecedented in Go: The predeclared constant iota exposes such a mechanism (it counts semicolons inside a const declaration, not unlike __LINE__ counts lines inside a file).

But I think introducing more such predeclared constants is not the right path. For one, __FILE__ and __LINE__ don't really fit into the aesthetics of Go. Also, it opens the door for ever more explicitly named such constants.

We do have other means to handle such things in a more Go-like way. I can think of 2:

  1. Introduce a new predeclared built-in function (better name choice welcome):
// compilerinfo accepts a string argument "filename", "line", or "timestamp" and returns the
// filename of the file being compiled, the line number of the compilerinfo invocation, or the
// time of compilation, respectively. The argument must be a constant string, and the result is
// a constant string.
func compilerinfo(string) string

Such a mechanism would be easily extensible. It would mean that we extend the language by this additional builtin.

  1. Introduce a new compiler-known magic package, say "compiler" (similar to package "unsafe"). Or maybe it should be in "unsafe" since results depend on file names, line numbers etc. which might not be considered "portable". Either way, such a packet could export functions like Filename(), Line(), Timestamp(), etc. that produce constant results (package unsafe does this already, so maybe that's the right place for these).

Something to think about.

@ianlancetaylor
Copy link
Contributor

I (now) agree that __FILE__ and __LINE__ can't be right.

It's hard for me to picture how these would be used. Not many people write out __FILE__ and __LINE__ in C code. Instead, they refer to them in macros. But obviously Go doesn't have macros, and you can get already the information in a function by using runtime.Caller. I don't think the concern about a hardcoded stack depth constant is valid, particularly if that depth is 1. That is, the equivalent of a C trace #define that uses __FILE__ and __LINE__ is a Go function that uses runtime.Caller(1) to find out its caller's file and line.

So I would like to see a real example of how these would be used before we even consider adding them.

@minux minux changed the title log: add __FILE__ and __LINE__ macro spec: add __FILE__ and __LINE__ macro Oct 8, 2015
@j16sdiz
Copy link
Author

j16sdiz commented Oct 9, 2015

@ianlancetaylor
I was trying to solve the concern in this comment sirupsen/logrus#63 (comment)

logrus have multiple logging code path and unstable internal API. Hardcoded stack depth are prone to bitrot.

I agree compiler magics are hard to use, but they are hard to break too.

@minux
Copy link
Member

minux commented Oct 9, 2015

Without going through the long issue, could you please give
an example where FILE and LINE macro could
help whereas calling runtime.Caller(0) won't?

@ianlancetaylor
Copy link
Contributor

It occurs to me that you can actually write these yourself very easily as functions.

func file() string {
    _, file, _, _ := runtime.Caller(0)
    return file
}

func line() int {
    _, _, line, _ := runtime.Caller(0)
    return line
}

Now for __FILE__ write file() and for __LINE__ write line().

I'm going to close this.

@mingodad
Copy link

Here is an implementation of it.
Go 1.6.2:
mingodad@d7eed61

Go master (1.7):
mingodad@6f7c067

For gccgo (6.1):
https://gist.github.com/mingodad/e9ccc835021f9004ef9d82d178c0f460

@golang golang locked and limited conversation to collaborators May 29, 2017
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

6 participants