I was extending Gorgonia for a project of mine when I rapidly ran into a dot-import gotcha in Go. Specifically I was trying to implement a fused version of the Conv2d
function that exists. The current Conv2d
function works well, if you want to do image convolution related work. It could be quite a bit faster (if anyone from Intel is reading, I’d love some help in the same way Intel boosted the speeds of Caffe), but that’s not really the concern - different convolution algorithms have different performance characteristics, and should be used accordingly.
Anyway, here’s the project directory:
PROJECT/
├── ops/
│ ├── convolution.go
│ ├── convolution_nocuda.go
│ └── convolution_cuda.go
│
├── main.go
The Conv2d
function I was writing was in ops/convolution.go
. It looked something like this:
package ops
import (
"gorgonia.org/gorgonia"
"gorgonia.org/tensor"
)
func Conv2d(im, filter *gorgonia.Node, kernelShape tensor.Shape, pad, stride, dilation []int) (retVal *gorgonia.Node, err error) {
return nil, nil // actual code here,
}
I go-built it, and ran into this error message:
$ go build .
./convolution.go:12:6: Conv2d redeclared in this block
previous declaration during import "gorgonia.org/gorgonia"
WTF?
As it turns out, it’s because I had this import in convolution_nocuda.go
, which actually implemented the op:
import (
. "gorgonia.org/gorgonia"
)
I had used it as a dot-import because unqualified imports look more like I’m writing parts of the Gorgonia package. I had assumed that the dot-imports were unqualified per-file. It’s not. It’s unqualified throughout the package.
The solution is simple: namespaces are useful. Use them.