Reference a symbol in a Go package without knowing if you are in that package? - go

Assume there is a function F in package A that some code I'm creating needs to call. How do I call it?
If I'm Calling it from outside package A, then I uses A.F(...) and if I'm inside A I uses F(...). But what if Murphy prevents me from knowing which is true or requires a byte identical line work in both?
[note: I'm taking it as a given that such a case will occur because, in my experience and observations, that is generally a safe assumption. Even in the absence of technical reasons for it, PHBs and legislators are good sources of the ridiculous.]

There is no such syntax. Observe the following things:
Cyclical imports are forbidden. This especially means that a package cannot import itself. Thus, a package cannot refer to one of its symbols S with the pkg.S syntax because it will not be able to import itself.
Even if you solved that problem, observe that packages can be given an arbitrary name once imported. For instance, you could do:
import bar "foo"
Which imports S from package "foo" as bar.S as opposed to the expected foo.S.
The following things could be used to work around this:
In the package "foo", create an internal object foo whose members are the symbols foo exports. This allows you to use the foo.S syntax in foo itself, but is a horrible kludge.
Use an import declaration like
import . "foo"
which allows you to use symbol S from package "foo" as S, i. e. without prefix. Notice that this kind of import declaration, called dot imports, is considered bad style and might break things if the set of symbols you declare / the package you import declares changes.

Related

How can I remove an unwanted import alias in Go?

I found that very useful Go library in the web https://github.com/deckarep/golang-set that tries to port Python sets to Go.
Thanks to Visual Studio Code I eventually got it to work by importing the library import "github.com/deckarep/golang-set" and calling a function in my code:
mySet := mapset.NewSet()
VS Code automatically recognizes the alias and replaces the import directive:
import mapset "github.com/deckarep/golang-set"
However, being someone who finds those aliases confusing, I was trying to remove it but doing so, VSCode removes it from both the import statements and my code. VS Code then tells me:
undeclared name: NewSet compiler(UndeclaredName)
The package name from NewSet(...) is also package mapset. So I thought I could simply remove it. But it does not work.
I also tried to work analogously to other 3rd party packages and call the functions by the repository's name:
mySet := golang-set.NewSet()
This also leads to an error. Is the removing of the alias not possible here due to the hyphen maybe or am I overseeing something else?
Several things here:
mapset is the package name. You can see this by looking at the package source code.
While the import alias, in this case, is not strictly needed from a language standpoint, it's added for clarity, since the package name (mapset) does not match the import path (golang-set). Without the alias in the import statement, there's no way to tell how the package is referenced. This is why it's important for it to be there.
You cannot use golang-set as your import name, becuase the - character is not permitted in an import alias. However, if you really want to, you could use golang_set or similar, by explicitly providing this as your alias:
import golang_set "github.com/deckarep/golang-set"
Note that this goes against naming conventions, in that packages should not have _ characters in the name. But it should still be valid.
Best practice would be just to use mapset as the alias. It's the least confusing of all the available options (which is why it's automatically selected).

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

Can I develop a go package in multiple source directories?

I am developing a go package, which is a little bit complex and thus I want to organize the source code into multiple directories.
However, I don't want the users of the package to have to use too long imports. Anyways, the internal structure of the package isn't their concern.
Thus, my package structure looks so:
subDir1
subSubDir1
subSubDir2
subDir2
subSubDir3
...and so on. All of them have their exported calls.
I would like to avoid that my users have to import
import (
"mypackage/subDir1"
"mypackage/subDir1/subSubDir2"
)
...and so on.
I only want, if they want to use an exported function from my package, they should have access all of them by simply importing mypackage.
I tried that I declare package mypackage in all of the .go files. Thus, I had source files in different directories, but with the same package declaration.
In this case, the problem what I've confronted was that I simply couldn't import multiple directories from the same package. It said:
./src1.go:6:15: error: redefinition of ‘mypackage’
"mypackage/mysubdir1"
^
./src1.go:4:10: note: previous definition of ‘mypackage’ was here
"mypackage"
^
./src1.go:5:15: error: redefinition of ‘mypackage’
"mypackage/mysubdir2"
^
./src1.go:4:10: note: previous definition of ‘mypackage’ was here
"mypackage"
^
Is it somehow possible?
You should not do this in any case, as the language spec allows a compiler implementation to reject such constructs. Quoting from Spec: Package clause:
A set of files sharing the same PackageName form the implementation of a package. An implementation may require that all source files for a package inhabit the same directory.
Instead "structure" your file names to mimic the folder structure; e.g. instead of files of
foo/foo1.go
foo/bar/bar1.go
foo/bar/bar2.go
You could simply use:
foo/foo1.go
foo/bar-bar1.go
foo/bar-bar2.go
Also if your package is so big that you would need multiple folders to even "host" the files of the package implementation, you should really consider not implementing it as a single package, but break it into multiple packages.
Also note that Go 1.5 introduced internal packages. If you create a special internal subfolder inside your package folder, you may create any number of subpackages inside that (even using multiple levels). Your package will be able to import and use them (or to be more precise all packages rooted at your package folder), but no one else outside will be able to do so, it would be a compile time error.
E.g. you may create a foo package, have a foo/foo.go file, and foo/internal/bar package. foo will be able to import foo/internal/bar, but e.g. boo won't. Also foo/baz will also be able to import and use foo/internal/bar because it's rooted at foo/.
So you may use internal packages to break down your big package into smaller ones, effectively grouping your source files into multiple folders. Only thing you have to pay attention to is to put everything your package wants to export into the package and not into the internal packages (as those are not importable / visible from the "outside").
Inside your package source code, you have to differentiate your source directories by renamed imports. You can declare the same package mypackage in all of your source files (even if they are in different directories).
However, while you import them, you should give an induvidual names to the directories. In your source src1.go, import the other directories on this way:
import (
"mypackage"
submodule1 "mypackage/mySubDir"
)
And you will be able to reach the API defined in "mypackage" as mypackage.AnyThing(), and the API defined in mySubDir as submodule1.AnyThing().
The external world (i.e. the users of your package) will see all exported entities in myPackage.AnyThing().
Avoid namespace collisions. And use better understable, intuitive naming as in the example.
Yes, this is doable without any problems, just invoke the Go compiler by hand, that is not via the go tool.
But the best advice is: Don't do that. It's ugly and unnecessarily complicated. Just design your package properly.
Addendum (because the real intention of this answer seems to get lost sometimes, maybe because irony is too subtle): Don't do that!! This is an incredible stupid idea! Stop fighting the tools! Everybody will rightfully hate you if you do that! Nobody will understand your code or be able to compile it! Just because something is doable in theory doesn't mean this is a sensible idea in any way. Not even for "learning purpose"! You probably even don't know how to invoke the Go compiler by hand and if you figure it out it will be a major pita.

Is there an efficient way to share structure between golang packages?

I have a short program in Go with the following files part of it.
Program directory structure:
myprogram/
main.go
server.go
routines.go
structs.go
These different files contain different function. The structs.go file contains a list of structure type defined, and used in several files of my program. What I want to do, now is to split my program into package like in this example :
main/
main.go // the main program
server/
server.go // a package imported in main
routines/
routines.go // a package imported in main
My problem, is that I do not know where to put structs.go because it contains structures used in several package, as in the 'main.go' code.
How to share efficiently this structs.go file ? Should I include it (via a symlink to the file) in each of the package I defined, i.e serverand routines and also in main ?
My method may be awkward because I'm a beginner in Go, and in programming generally.
Don't link files across packages, that's bad practice. For one, the code will be duplicated. For another, identifiers will be duplicated meaning to denote the same entities (e.g. type or function), but they will be distinct. E.g. if linked and structs.go would contain a type Response definition, you would have 2 distinct types server.Response and routines.Response giving just more confusion.
One solution would be to put structs.go into its own package, e.g. model, and all other packages relying on it can import it (e.g. your main, server and routines).
In a theoretical example: if package A imports package B and structs.go would be needed in both, then it could also be added to package B. If there would be a package C needing only structs.go, then again it would be wiser to create its own package model (so package C doesn't need to import / know about package B, only the new model package).
Also if noone else will use your package and it is not too complex, it might not worth the hassle to organize it into multiple packages.
It is possible to define a type in one package only and to use it in other packages this way:
package one
type A struct{ B int }
Variant 1:
package two
. import "one"
var name A
Variant 2:
package two
import "one"
type A = one.A
var name A
I would prefer variant 2.

how to include files in D source code, just as it is done in C

that is:
#include "mySnippet.h"
Does D even have such thing ?
Using import "myInclude.d" procuces:
test.d(5): Error: Identifier expected following import
test.d(5): Error: ';' expected
The only thing that is remotely similar to the C/C++ #include statement is the in-place import of a file, and then mixing that into the source:
mixin(import("mySnippet.d"));
D is a modular programming language and the import statement is your friend when you do D programming.
In D you really do not need anything like #pragma once. This extension, and include-guards are there because C and C++ do not care about these things. D does.
However, I assume you are probably wondering how you give the interface to your clients in case you create a library and you do not want to expose the internals. For this purpose the DPL team came up with the D interface files in order to solve this problem. So, you simply give the interface files to your client along with your library, and job is done.
See the reference file at: http://dlang.org/module.html
The imports are done like this (extracted from there):
import std.stdio; // import module stdio from package std
import foo, bar; // import modules foo and bar
void main() {
writefln("hello!\n"); // calls std.stdio.writefln
}
And modules are created like this:
module A;
void foo();
void bar();
The D style is:
import myinclude;
D doesn't have a textual include like C.
D doesn't include files in the same way as C/C++.
C/C++ actually copies the contents of the included file at the location of the #include, which is why the '#pragma once' or other inclusion guard is required, because the code will really be copied for each time it is in a #include line.
D doesn't bother with copying the source around, and compiles each source file into its own object file. The 'import' command in D asks for the symbols (or the names of each function, class, struct, enum, and variable) found in the module that is asked for. The compiler then just has to connect these object files together into the executable. Well, there's a bit more to it than that, but that should be accurate enough for this.
Also, as Mr Ruppe said, there is no need to enclose the name of the source file in quotes, nor do you need to add the file extension to the name.
If, for example, you have your main() function in main.d, and you want to include a source file called foo.d, that is in the same folder as main.d, then you type the following into main.d;
import foo;
and in foo, you would have;
module foo;
<other code here>
Hope this helps. Most of this is also on http://dlang.org, on their 'modules' page under the language definitions.

Resources