When attempting to import to files from the windows file system:
import (
pb "github.com\\sewelol\\sgx-decryption-service\\decryptionservice"
dev "github.com\\sewelol\\sgx-decryption-service\\device"
"google.golang.org\\rpc"`
)
I get this error
server\main.go:10:5: invalid import path: "github.com\\sewelol\\sgx-decryption-service\\decryptionservice"
I have checked $PATH enviroment variable includes the directory that has github.com, and $GOROOT also is set up to point to the Go installation.
I assume it is something to do with the file paths themselves, but I can't find any information on how to do filepaths in the windows environment.
Thanks
You have to use forward slashes / in import paths (of import declarations), even if you're on Windows.
Spec: Import declarations:
Implementation restriction: A compiler may restrict ImportPaths to non-empty strings using only characters belonging to Unicode's L, M, N, P, and S general categories (the Graphic characters without spaces) and may also exclude the characters !"#$%&'()*,:;<=>?[\]^{|}` and the Unicode replacement character U+FFFD.
Any compiler may exclude the backslash \ character among others. Even if you would use one that doesn't, your code would not be portable.
So instead try:
import (
pb "github.com/sewelol/sgx-decryption-service/decryptionservice"
dev "github.com/sewelol/sgx-decryption-service/device"
"google.golang.org/rpc"
)
Related
I am import two different proto files in my current proto file as below
import "author/message/name.proto"
import "reader/message/details.proto"
in name.proto I have go_package = "author/message" and in details.proto I have go_package = "reader/message" because of which when pb.go is generated import alias is showing as below
message1 "author/message"
message2 "reader/message"
I am trying to find a way where i can name alias like authormsg and readermsg respectively during pb.go generation. I have checked documentation but couldnt find anyway to do that.
You can add the explicit Go package name like this:
name.proto: option go_package="author/message;authormsg"
details.proto: option go_package="reader/message;readermsg"
Means you add the package name separated with a semicolon (;) after the import path.
Note:
This usage is discouraged since the package name will be derived by default from the import path in a reasonable manner.
Protocol Buffers documentation
I'm mostly familiar with Python and a bazel build environment. I'm trying to rewrite a portion of code in Go and I'm struggling to get the proto imports to align properly.
In github.com/djhedges/exit_speed/gps.proto I have set go_package like so
option go_package = "github.com/djhedges/exit_speed/gps_go_proto";
I've added a reflector.proto which imports gps.proto and reuses some of the messages defined in there.
import "gps.proto";
I compile gps.proto with
protoc -I ./ --go_out=./ --go_opt=paths=source_relative --python_out ./ gps.proto
And compile reflector.proto with
LD_PRELOAD=/usr/lib/arm-linux-gnueabihf/libatomic.so.1 python3 -m grpc_tools.protoc -I ./ --go_out=./ --go_opt=paths=source_relative --python_out ./ --grpc_python_out ./ reflector.proto
And finally in exit_speed/reflector.go I try to import gps_go_proto with
import gpspb "github.com/djhedges/exit_speed/gps_go_proto"
Which errors with
go: finding github.com/djhedges/exit_speed/gps_go_proto latest
reflector.go:21:2: unknown import path "github.com/djhedges/exit_speed/gps_go_proto": cannot find module providing package github.com/djhedges/exit_speed/gps_go_proto
I would prefer to keep gps.proto in the root directory if possible because I have protos logged into data files and I believe moving this breaks the proto parsing. I suppose I could write a migration script.
I'm also confused as to how setup multiple protos with different go packages and imports. Do go packages have to have a dedicated folder?
If I'm understanding go packages correctly the package name must map to a directory. By changing --go_out=./ to --go_out=./gps_go_proto seems to solve my issue without having to move the proto files. It does mean I have some additional directories but that seems okay.
As the Go Specification import section says:
Import declarations
An import declaration states that the source file containing the declaration depends on functionality of the imported package (§Program initialization and execution) and enables access to exported identifiers of that package. The import names an identifier (PackageName) to be used for access and an ImportPath that specifies the package to be imported.
ImportDecl = "import" ( ImportSpec | "(" { ImportSpec ";" } ")" ) .
ImportSpec = [ "." | PackageName ] ImportPath .
ImportPath = string_lit .
(snipped here, and I broke some links; use the first link to get the text with the links). The string literal is the familiar:
import "github.com/..."
part; the PackageName, or a dot, are optional. Returning to the text:
The interpretation of the ImportPath is implementation-dependent but it is typically a substring of the full file name of the compiled package and may be relative to a repository of installed packages.
In your own answer, you add:
If I'm understanding go packages correctly the package name must map to a directory.
That's not necessarily so. It's up to the implementation to decide what the string literal means. In general, though, the Go build system will find a directory full of files, using this path. It may also use a version control system, such as Git, to fill a directory full of files, so that the compiler can find them.
Something that I found a bit surprising, but in the end, makes perfect sense (and is described in the spec), is this: the package name found in the package clause:
package somename
statement at the top of some imported file, is sometimes irrelevant. A directory full of files that implement package x will have them all say package x, of course. But it's the y identifier in the line:
import y "path/to/x"
in your package that supplies the name you use to access exported identifiers. The name you use here, with the import having y as the package name, is y, even if the package itself says package x. The package clause in package x is, in effect, just recommending the name x, so that you can write:
import "path/to/x"
if you'd like to refer to these as x.Thing.
There's no need for the string literal to mention x either: perhaps all the files are in something found via path/to/z, and you write:
import "path/to/z"
and then (still) write x.Thing because files in path/to/z/*.go recommend x as the package name.
How protoc uses this
Regardless of the above, the protobuf Go generators will print, in the generated name*.pb.go* Go code, an import directive. That import directive will read:
import "some/path/here"
You can specify the string literal using option go_package. The protobuf compiler doesn't need to interpret this itself. But, as the documentation notes, these name.pb.go files themselves will be dropped into a directory somewhere. They will also contain a package pkg line, of course.
The location of each output file depends on whether you use --go_opt=paths=source_relative. If you do, the go_package option string becomes irrelevant here.
The .pb.go file generator takes the go_package option string, strips off everything up to and including the last slash, and uses the remaining string for the package line.
The second point means that regardless of what the Go system itself does, how it finds these files, and how you write your own imports, the recommended package name in those files will be the last component of whatever was in the go_package option. So in a sense, all you really need is the final component. But if your Go implementation needs more than that, you can supply more.
The first point means that if you don't use --go_opt=paths=source_relative, the rest of the text in the go_package option matters: the Go generator will try to use that string to produce output files. So if your Go implementation needs more, and you do supply more, and it doesn't match what you want for output file names, you'll definitely need the --go-opt.
I installed a package (FsLab), i load it like this:
#load "packages\FsLab\FsLab.fsx"
But then i get an error
Could not load file C:\Users\myname\Desktop\Tutorial1\packages/<packagename>' because it does not exist or is inaccessible
Which is understandable, since the main directory contains backward slashes and the directory to the package contains forward slashes. I have checked in the files of the package and like i guessed it, it contains sub packages that are forward slashed
How to fix this this so that the slashes of the main directory are forward?
It is fixed by changing the load file:
#load #"..\packages\FsLab.1.0.2\FsLab.fsx"
The # sign from the microsoft page:
When placed before a string literal, indicates that the string is to
be interpreted verbatim, with no interpretation of escape characters.
https://learn.microsoft.com/en-us/dotnet/fsharp/language-reference/symbol-and-operator-reference/
I am using a third party library in GoLang that has previously had import paths in different case. Initially a letter was lower case then the author changed it to uppercase.
Some plugin authors updated their libraries and others didn't. In the meantime the original library author reverted the case change.
Now I find myself in a state where my application won't build due to to case import collisions.
How can one go about fixing this?
Many thanks
You could vendor the dependencies, and then go into the vendor/ directory and manually change (try greping or seding the dependency), the dependencies.
For an introduction to vendoring, try here, https://blog.gopheracademy.com/advent-2015/vendor-folder/
The original repo can still live in your GOPATH, but the 'corrected' version can go in the vendor folder, in which the compiler will look first when linking dependencies.
There are many tools for vendoring, I use govendor
Edit
As mkopriva mentions in the comments, you can refactor import names using the gofmt tool:
gofmt -w -r '"path/to/PackageName" -> "path/to/packagename"' ./
gofmt -w -r 'PackageName.x -> packagename.x' ./
The lowercase single character identifier is a wildcard.
from the docs
The rewrite rule specified with the -r flag must be a string of the form:
pattern -> replacement
Both pattern and replacement must be valid Go expressions. In the pattern, single-character lowercase identifiers serve as wildcards matching arbitrary sub-expressions; those expressions will be substituted for the same identifiers in the replacement.
Just if anyone wonders why this error might occur in your project: Make sure all imports use either lowercase or uppercase path, but not mixed.
So like this:
one.go -> "github.com/name/app/login"
another.go -> "github.com/name/app/login"
And not like this:
one.go -> "github.com/name/app/Login"
another.go -> "github.com/name/app/login"
echo $GOPATH
/Users/me/go/
In go the code below outputs /Users/me/go: . Notice :
package main
import "os"
import "fmt"
func main(){
p := os.Getenv("GOPATH")
fmt.Println(p)
}
However I've tested it on linux and the dots (:) are replaced by a slash ( which I think is the correct form so we have /Users/me/go/. I'm wondering why is this inconsistency and if it's actually a bug.
System Info:
go version
go version go1.3 darwin/amd64
OS: OSX 10.7.5
The GOPATH environment variable is a list of paths. On Unix-like operating systems, the value is a colon-separated string of paths. For example,
/Users/me/go/:/Users/all/go/
or
/Users/me/go:/Users/all/go:
Command go
GOPATH environment variable
The Go path is used to resolve import statements. It is implemented by
and documented in the go/build package.
The GOPATH environment variable lists places to look for Go code. On
Unix, the value is a colon-separated string. On Windows, the value is
a semicolon-separated string. On Plan 9, the value is a list.
Go searches each directory listed in GOPATH to find source code, but
new packages are always downloaded into the first directory in the
list.