how to implement macros in Go? - go

I've project done in C++ where I used #define macros to give a name of the project, which I used in several places, I don't change this name often but sometimes I may need to change this, then I change this macro and rebuild my code. Now I'm converting this code to Go. Can someone suggest me how to implement this in Go? I'm not interested in using global variables for this purpose because I've many such macros and I doubt this cause my project to occupy more cpu and effect the performance.

Luckily, Go does not support macros.
There are two venues in Go to implement what is done using macros
in other programming languages:
"Meta-programming" is done using code generation.
"Magic variables/constants" are implemented using "symbol substitutions"
at link time.
It appears, the latter is what you're after.
Unfortunately, the help on this feature is nearly undiscoverable
on itself, but it explained in the output of
$ go tool link -help
To cite the relevant bit from it:
-X definition
add string value definition of the form importpath.name=value
So you roll like this:
In any package, where it is convenient,
you define a string constant the value of which you'd like to change at build time.
Let's say, you define constant Bar in package foo.
You pass a special flag to the go build or go install invocation for the linking phase at compile time:
$ go install -ldflags='-X foo.Bar="my super cool string"'
As the result, the produced binary will have the constant foo.Bar
set to the value "my super cool string" in its "read-only data" segment,
and that value will be used by the program's code.
See also the go help build output about the -ldflags option.

Go doesn't support Macros.
but you can use a constants inside a package and refer it where ever you need.
package constant
// constants.go file
const (
ProjectName = "My Project"
Title = "Awesome Title"
)
and in your program
package main
import "<path to project>/constant" // replace the path to project with your path from GOPATH
func main() {
fmt.Println(constant.ProjectName)
}
The project structure would be
project
|- constant
| |- constants.go
|-main.go

Related

'Vertex' redeclared in this pacakge

I have a Go project in JetBrains goland where all files are runnable yet independent of each other.
But to make every runnnable, I need to make them as package main.
And I have several "Vertex" defined elsewhere in other file and Goland complain about it.
But it is still runnable, and that's purely complaint from Goland.
Question -
Is there a better way to organized the files?
If not, is there a way to turn off the complaint from Goland?
Working with multiple files that declare the main() function in the same directory is not recommended in general, mainly due to problems similar to yours.
However, there are several ways to solve this.
You can use build constraints, also known as build tags, to separate the binaries at build time. When using them, the IDE will also need to be adjusted using the Settings/Preferences | Build Tags & Vendoring. And, depending how you build your application, you might also need to adjust the build command to add the corresponding tags to it.
The other option, which I'd recommend in this case, is to move each main() defining file into a structure such as this:
/repository_root
/cmd
/command1
command1.go (file holds the `main()` func)
/command2
command2.go (file holds the `main()` func)
/command3
command3.go (file holds the `main()` func)
/some
/package
some_file.go
some_other_file.go
....
some_other_file.go
As an example of this layout, you can have a look at Delve, which uses a similar structure, but only has a single "command" in the cmd folder.
Lastly, sometimes it's possible to remove the duplication and move it to a common file which holds the data type, but it's not always ideal and can make the build command more complex, since you need to specify all the files that should be included in the build process.
Edit:
And you can read more on how to organize your Go packages/applications here
These articles will explain how to organize your Go packages:
https://rakyll.org/style-packages/
https://medium.com/#benbjohnson/standard-package-layout-7cdbc8391fc1#.ds38va3pp
https://peter.bourgon.org/go-best-practices-2016/#repository-structure
To understand more about the design philosophy for Go packages: https://www.goinggo.net/2017/02/design-philosophy-on-packaging.html

Does using the same package pollute the compiled binary?

TL;DR:
Do test written within a package end up in the final exported package? Do they add any garbage or weight to a compiled binary?
Longer version:
Let's say that I have a foo Go package:
pkg/
foo/
bar.go
bar_test.go
I'm aware of the black box vs white box approaches to testing in go. A short recap is that I can either:
have bar_test.go declare a foo_test package, or
have it part of the main foo package.
Approach 1 provides better isolation because it allows to focus on the public API of the package, as one only access the exported identifiers of foo. Also, when application code imports the foo package with import "pkg/foo", only the files containing the main foo package are compiled. That's nice. [1]
However, there are cases where putting the tests in foo is a convenient compromise. I don't particularly like it myself, but I can see it in several codebases and I understand why at times it's necessary.
My question is about what happens to these tests. Since they're part of the package foo, when foo is imported somewhere, I'd expect the tests to be brought along. Or is the compiler smart enough to strip them?
[1] this is not a question on what approach is "better". It's doesn't really matter. Please abstain from commenting with "that approach is not better".
Yes, the Go tool is smart enough not to pass them to the compiler.
https://github.com/golang/go/issues/10184

Name for a generated go file

I'm generating a Go file (to include constants such as build version etc) so that the constants can be used in other packages. I have a created a small tool that will create the file with go generate but am trying to think of an appropriate name so that
It is obvious that it is generated, so if it is missing (on build) the user then knows to run go generate
And I can then add the file to the .gitignore
My first guess is something like version_GENERATED.go
Any conventions I should be aware of or better suggestions?
Having a suffix like _GENERATED added to the file name does not hold any information until the file is generated, as the compiler will just give you "unrelated" errors like "undefined: xxx" (the compiler won't guess that if the identifier would exists, it would be in version_GENERATED.go).
For example the stringer generator generates files with name type_string.go where type is replaced with the name of the type it is generated for.
So I think simply following the general guidelines for file names is enough, except maybe use _gen or _generated suffix. Or if your tool is public and used by others too, then use the name of the tool as the suffix (like stringer does).
If you do want the user to get a talkative error message in case your generator is yet to be run, your generator may generate an exported constant whose name is talkative if included in an error message, like:
const MustRunStringerGenerator = 0
And in your program refer to it like:
var _ = MustRunStringerGenerator // Test if stringer has been run
If stringer has not yet been run, you'll see an error message:
undefined: MustRunStringerGenerator

Go language: Using package name inside package scope (for Examples)

I am currently writing ExampleFuncs in my Go test scripts. For example:
package hello
import "testing"
func ExampleGetSymbol() {
data := GetSymbol("AAPL")
fmt.Println(len(data.Data))
// Output: 21
}
Now, this gives me two benefits:
This example is executed when I am running go test and
It appears in the godoc documentation under func GetSymbol
One thing bothers me and I am wondering if there is anything I should do about it.
For the user that's trying to learn from this example, the line
data := GetSymbol("AAPL")
should actually be
data := hello.GetSymbol("AAPL")
but since the test is in the same scope as the package, I cannot use it like this.
So I guess the distilled version of my question would be:
Is there a way to allow package.field notation inside the package scope?
Thanks in advance
Rather than putting this in package hello, put it in package hello_test. You're allowed to have both hello and hello_test packages in the same directory, and it allows (requires) you to create your examples the way you're suggesting.
Incidentally, this also causes you to write your test cases (at least for this file) only to the public API. This is often a good thing. But if you need to write to private functions, you can split your tests into separate files, some in the hello package and some in hello_test.
BTW, documentation for this is slightly buried. You can find it in the "Test packages" section of the go cmd documentation.

Using code defined in separate file in Go

Say I have got code for a project spread across multiple files. Is there any other way to reference such code within files in the project without going through the whole build and install process? For example within a single project, I might have an implementation of a type Foo in file A and I might want to use such type in file B within the same project. Is there anyway to go about doing that
It's not clear to me what exactly you're asking about, but this part of the language specs about "Declarations and scope" might be related and/or helpful. Another, more prosaic source of related information might probably be "How to Write Go Code".
EDIT - Expanding on now expanded question:
If "package a" declares type Foo - then, b/c Foo starts with an upper case letter - Foo is exported by a. Then in "package b" one would write import "a" and can then refer to that type as a.Foo inside "package b".

Resources