How to split a large package without breaking client code? - go

Let's say I have a library package called foobar.
Over time it became big and heavy.
Fortunately it's separable, I managed to split its functionality into two separate packages foo and bar -- most clients will only need to use one or the other.
Since my library is already in use by many clients, for compatibility I still want to maintain a foobar package as a proxy to the current functionality found in both foo and bar.
How does one achieve this in Go ?
One way that comes to mind is to create aliases in foobar for each struct/function in foo and bar. So if foo defines F() and bar defines B(), I would have in foobar:
var (
F = foo.F
B = bar.B
)
But I am hoping for an easier/cleaner way.

Creating an alias package is the only way.
But your attempt probably won't work: It works only for functions and variables and consts but not for types. For types you have to duplicate the type in foobar.
I wouldn't do this. Just have foobar around in version 1 and start anew with foo and bar (maybe directly in version 2).

Related

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

How can I enforce a compiler warning or error for namespace conflicts?

Consider I have the following:
FrameworkA, which defines class Foo
FrameworkB, which also defines class Foo
A file in FrameworkA which imports FrameworkB
How can I get Xcode to generate either a warning or error on any line that makes references to Foo without using the namespace qualifier?
For example:
let a = FrameworkA.Foo() // fine, no warning or error
let b = FrameworkB.Foo() // fine, no warning or error
let c = Foo() // at a minimum, a warning
I understand completely that if we are in FrameworkA, then the third example is equivalent to FrameworkA.Foo(), but I would like for Xcode to generate a warning or error.
Consider the scenario when class Foo has existed in FrameworkB for a long time, and the line of code in question has always intended to point at the class Foo defined in FrameworkB, but at some later point in the future, someone added class Foo into FrameworkA for some reason. This would change the behavior of the line in the file.
I would like Xcode to generate compile time warnings or errors any time something defined in multiple frameworks imported into a file is used without the namespace being explicitly declared.
Is there a way?
I don't think at this point Xcode supports this unfortunately - some less fruitful solutions:
Open a radar task, and hope that Apple fixes it.
Prefix your classes (as we used to do with Obj-C)
The second option should be viable for most projects; instead of Foo and Foo, you will have LIBAFoo, LIBBFoo, but in practice, with more meaningful prefixes i.e. CA → Core Animation.

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

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.

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

Windows Static Library with Default Functions

I would like to create a static library (.lib) in Windows that can be used in subsequent builds as a "backup" for undefined functions.
For instance let's say I have foobar.lib which has definitions for:
FOO
BAR
and I have some other program that defines FOO only and is to be built into a DLL that must export FOO and BAR. I want to be able to use foobar.lib to automatically export the default definition of BAR in the resulting DLL (and ignore the definition of FOO in foobar.lib).
I have tried sending foobar.lib to the linker but I get a multiple defined symbols error (/FORCE is supposed to override that but with strong warnings that it probably won't work as expected). I've also tried using /NODEFAULTLIB:foobar.lib but then it completely ignores the library and says BAR is undefined.
I am almost 100% certain there is a way to do this because I use an application that does this (Abaqus) to allow users to write plug-ins and not have to define all of the required exports for the plug-in DLL. And they do not use the /FORCE option.
I figured out a solution (not sure if it is the only or best solution).
I was trying to define FOO and BAR in foobar.lib using one object file (foobar.obj). If I split it up into foo.obj and bar.obj and then use those to create foobar.lib the linker can effectively ignore the appropriate .obj files.
So the short answer is: one function per object file for the static library.

Resources