Why can't I start a simple GRPC server with Go? [duplicate] - go

This is my code structure:
addition
|_ summing
|_ sum_prg.go
|_ addition.go
|_ go.mod
Contents of go.mod
module addition
go 1.14
Contents of sum_prg.go
package summing
func sumIt(ii int) int {
return ii + 10
}
Contents of addition.go
package main
import (
"fmt"
"summing"
)
func main() {
fmt.Println("hi")
fmt.Println(summing.sumIt(1))
}
Here's the steps I've run:
Inside addition folder, go mod init addition
Inside summing folder, go build
Back in addition, go install addition
In step 3 I get an error "addition.go:5:2: package summing is not in GOROOT (c:\go\src\summing)"
This is my first go programming attempt.
I can successfully follow the steps listed here, but when I try to follow the same steps, I see the error mentioned above.
Do I always need to have module names of the form somethng.com/else?

You can see from the module FAQ
Do modules work with relative imports like import "./subdir"?
No. See #26645, which includes:
In modules, there finally is a name for the subdirectory.
If the parent directory says "module m" then the subdirectory is imported as "m/subdir", no longer "./subdir".
So, as commented, use "addition/summing" (with exported method name) for your import from main.

Related

Hello world in Goland

I'm following the official Go tutorial: https://golang.org/doc/code.html
But instead of doing things via the command line I'm using GoLand. I'm able to run the program and see "Hello World" printed when everything is contained inside the HelloWorld.go package, but when I add the morestrings package and try to import it in HelloWorld.go I get an import error (Cannot resolve file 'morestrings'):
package main
import (
"morestrings"
"fmt"
)
func main() {
fmt.Println(morestrings.ReverseRunes("!oG ,olleH"))
}
Here's what I've defined the morestrings package to be:
package morestrings
// ReverseRunes returns its argument string reversed rune-wise left to right.
func ReverseRunes(s string) string {
r := []rune(s)
for i, j := 0, len(r)-1; i < len(r)/2; i, j = i+1, j-1 {
r[i], r[j] = r[j], r[i]
}
return string(r)
}
I've set the GOPATH in project settings to the root directory of my project (GoGoHelloWorld). My understanding is that Go will look for imports starting at GOPATH, so I would expect it to find the morestrings package. Here's the file structure:
First, I think you can take a look at this go project layout which may diffs with other language like C++ or Java.
Second, I would like using go module.
If your go path is GOPATH=/Users/.../IdeaProjects/FinalGoHelloWorld.
I am assuming you have created a project "GoGoHelloWorld" inside "FinalGoHelloWorld".
Your import statement is wrong, you should use "GoGoHelloWorld/src/morestrings"
When you try to import a package in GO, it doesn't look for that package everywhere in the whole file system, it looks for that package in specific folders.
These folders are the src folder inside your GOROOT and GOPATH directory.
All your code should be place inside this GOPATH's src folder.
You mentioned in the comments section GOPATH=/Users/.../IdeaProjects/FinalGoHelloWorld. So you must create a src folder inside this directory and all the code goes inside src.
So your GoGoHelloWorld folder's full path must be /Users/.../IdeaProject/FinalGoHelloWorld/src/GoGoHelloWorld, so now your import should look more like
import (
"GoGoHelloWorld/src/morestrings"
"fmt"
)
For reference, since your GOROOT is GOROOT=/usr/local/go your fmt package(folder) will be loacted at /usr/local/go/src/fmt
I would also recommend changing the GOPATH folder name from FinalGoHelloWorld to something more generic like GoWorkspace. So inside GoWorkspace/src you could create multiple projects folders with specific name.
One last thing, create two more folders, bin and pkg, along with srcinside GOPATH

Issue when importing a go package

This is my code structure:
addition
|_ summing
|_ sum_prg.go
|_ addition.go
|_ go.mod
Contents of go.mod
module addition
go 1.14
Contents of sum_prg.go
package summing
func sumIt(ii int) int {
return ii + 10
}
Contents of addition.go
package main
import (
"fmt"
"summing"
)
func main() {
fmt.Println("hi")
fmt.Println(summing.sumIt(1))
}
Here's the steps I've run:
Inside addition folder, go mod init addition
Inside summing folder, go build
Back in addition, go install addition
In step 3 I get an error "addition.go:5:2: package summing is not in GOROOT (c:\go\src\summing)"
This is my first go programming attempt.
I can successfully follow the steps listed here, but when I try to follow the same steps, I see the error mentioned above.
Do I always need to have module names of the form somethng.com/else?
You can see from the module FAQ
Do modules work with relative imports like import "./subdir"?
No. See #26645, which includes:
In modules, there finally is a name for the subdirectory.
If the parent directory says "module m" then the subdirectory is imported as "m/subdir", no longer "./subdir".
So, as commented, use "addition/summing" (with exported method name) for your import from main.

Go 'mod init' creating new folders? what is the significance of path?

Just 3 days experience in Go language. Hope an example will be more apt to understand my confusion.
root#freebsd1:/usr/home/arun/go-start/src/test2 # go mod init f1/f2/f3/f4/f5/hello
go: creating new go.mod: module f1/f2/f3/f4/f5/hello
root#freebsd1:/usr/home/arun/go-start/src/test2 #
Here in above example go mod init is creating all these folders(f1/f2/f3/f4/f5/hello)?. I searched a lot, couldn't find any such folders in system. Then what is the significance of this path.
Even though below command will not run if this path is not mentioned as it is
# go install f1/f2/f3/f4/f5/hello
--:EDIT:--
May be this will help someone later ( Just walk through the steps to understand this in a proper way, especially for newbies )
I am planning to create a program 'calculator' and will upload in GitHub later.
I will keep the functions in different packages like sum,multiply etc
first step #go mod init github.com/go-arun/calculator( Don't confuse here , this is just an assumption that, in future I may create a repository in github for this project )
created folder sum(one of the package folder , and created sum.go inside )
See those in by system:
1.
root#debian1:/home/arun/lab# go mod init github.com/go-arun/calculator
go: creating new go.mod: module github.com/go-arun/calculator
root#debian1:/home/arun/lab# cat go.mod
module github.com/go-arun/calculator
go 1.15
2.
root#debian1:/home/arun/lab# cat sum/sum.go
package sum
import "fmt"
func Sum(num1,num2 int)(){
fmt.Println(num1+num2)
}
3.
root#debian1:/home/arun/lab# cat main.go
package main
import(
"github.com/go-arun/calculator/sum"
)
func main(){
n1 := 10
n2 := 10
sum.Sum(n1,n2)
}
4.
root#debian1:/home/arun/lab# tree
.
|-- go.mod
|-- main.go
`-- sum
`-- sum.go
go mod init does not create those folders. You pass the "module path" to go mod init which is recorded in the go.mod file it creates.
The "module path" is the import path prefix corresponding to the module root. The module path and the relative path to the module root together form the complete import path which must be unique in an app.
So for example if your module contains a folder named foo (and a package foo in it), it is imported by a path being modulepath/foo. In your case it would be f1/f2/f3/f4/f5/hello/foo.
It is allowed for moduleA to contain a foo package, and also for moduleB to have a foo package. When used / imported, first would be imported like moduleA/foo the latter like moduleB/foo, so it's unambiguous which one you're importing. The module path is like a namespace.
It's recommended to use a module path that corresponds to a repository you plan or will publish your module to, so when you do, go get will be able to automatically fetch, build and install your module. For example you may choose a module path github.com/bob/hello, so when you publish your module, everyone can get it by simply using import "github.com/bob/hello" in their app.
Also note that you don't need to publish your code to a remote repo before you can build it. But it's still recommended to follow this pattern so you'll have less work to make it work in the future if you decide to publish it. Nothing to lose here.
More in the docs: Command go: Defining a module
Also: How to Write Go Code: Code organization

Relative imports in Go

I have a go Project with the following directory structure
utils(pkg)
| auth.go (has a function names test1)
controllers(pkg)
| login.go (has a function names test2)
I am trying to access function test1 from login.go. Here is what I have done
import "../utils"
func test2(c *gin.Context) bool{
utils.test1()
}
But I always get Unresolved reference test1. I am new to go . Can anyone help why I am getting this error?
No there is no relative import in Go.
you should use the absolute path considering GOPATH:
The GOPATH environment variable specifies the location of your workspace. It is likely the only environment variable you'll need to set when developing Go code. To get started, create a workspace directory and set GOPATH accordingly. see: https://golang.org/doc/code.html#GOPATH
Import paths
An import path is a string that uniquely identifies a package. A package's import path corresponds to its location inside a workspace
or in a remote repository (explained below).
The packages from the standard library are given short import paths
such as "fmt" and "net/http". For your own packages, you must choose a
base path that is unlikely to collide with future additions to the
standard library or other external libraries.
If you keep your code in a source repository somewhere, then you should use the root of that source repository as your base path. For
instance, if you have a GitHub account at github.com/user, that should
be your base path.
Note that you don't need to publish your code to a remote repository
before you can build it. It's just a good habit to organize your code
as if you will publish it someday. In practice you can choose any
arbitrary path name, as long as it is unique to the standard library
and greater Go ecosystem.
Example:
This example assumes you have set GOPATH=/goworkdir in your OS environment.
File: goworkdir/src/project1/utils/auth.go
package utils
func Test1() string {
return "Test1"
}
File: goworkdir/src/project1/controllers/login.go
package controllers
import "project1/utils"
func Test2() string {
return utils.Test1()
}
File: goworkdir/src/project1/main.go
package main
import (
"fmt"
"project1/controllers"
)
func main() {
fmt.Println(controllers.Test2())
}
Now if you go run main.go you should see output:
Test1
This is now different since the introduction of go modules, from go 1.11.
Thus, if you switch to go modules, and if your module is called "m", then the idiomatic way to do relative imports in your project tree would be to use: import "m/utils" and import "m/controllers" in places where you need to import those packages in your project.
For details, see:
https://github.com/golang/go/wiki/Modules#do-modules-work-with-relative-imports-like-import-subdir
GoLand users - by default these forms of imports appear as errors in the IDE. You need to enable Go Modules integration in settings
Here is another example project structure with file contents required to import correctly:
test1/
utils/
texts.go
main.go
go.mod
with following contents:
go.mod:
module mycompany.com/mytest
go 1.15
utils/texts.go (to make a function visible from a different package, it needs to start with an uppercase letter):
package utils
func GetText() string {
return "hello world"
}
main.go (only the full import name is supported, there is no shortcut to import from the same module easier):
package main
import (
"fmt"
"mycompany.com/mytest/test1/utils"
)
func main() {
fmt.Println(utils.GetText())
}
Given this directory configuration:
.
├── controllers
│   └── login.go
├── main.go
└── utils
└── auth.go
File main.go:
package main
import "./controllers"
func main() {
controllers.Test2("Hello")
}
File controllers/login.go:
package controllers
import "../utils"
func Test2(msg string) {
utils.Test1(msg)
}
File utils/auth.go:
package utils
import . "fmt"
func Test1(msg string) {
Println(msg)
}
Result works:
$ GO111MODULE=auto go build -o program main.go
$ ./program
Hello
So what you wanted to do works. The only difference is that I've used upper case function names, because it's required to export symbols.
I think you can just crate a vendor directory next to your source file, which acts like a relative GOPATH, and then create a relative symlink, which links to the package you want to import inside the vendor directory, and then import the package as if the vendor directory is your $GOPATH/src/.
It's possible as of Go 1.16, although still not as straightforward as it could be, by editing the go.mod file to resolve the package name to a relative path:
if you have a hello and a greeting packages side by side (hello contains main.go):
<home>/
|-- greetings/
|--go.mod <- init this as infra/greetings
|--greetings.go <- let's say that this package is called greetings
|-- hello/
|--go.mod <- init this as whatever/hello
|--main.go <- import infra/greetings
then edit hello's go.mod file and get the package:
go mod edit -replace infra/greetings=../greetings
go get infra/greetings
go mod tidy
There's a full example in the official documentation but hey, this might change again in the next version of Go.

Does it make sense to have two packages in the same directory?

I have a project that provides a library (exports some funcs) and also must provide a command-line interface (there must be an executable file).
Example of directory structure:
whatever.io/
myproject/
main.go
myproject.go
The go compiler needs the package main and func main to start execution. My library needs the package myproject where I put stuff on it. This is what the go tool says when I am building another project that tries to import myproject:
main.go:5:2: found packages myproject (myproject.go) and main (main.go) in $GOPATH/src/whatever.io/myproject
So I believe there is no way to do it.
Should I move the library or the CLI to another package?
Just move your packages inside a new folder within the same directory of main.go.
Remember to import the new package from the reference of the $GOPATH.
Example:
user#user:~/p/go/test/so-multipack$ ls -R
.:
a main.go
./a:
a.go
user#user:~/p/go/test/so-multipack$ cat main.go
package main
import (
"../so-multipack/a"
)
func main(){
a.Hello()
}
user#user:~/p/go/test/so-multipack$ cat a/a.go
package a
import (
"fmt"
)
func Hello(){
fmt.Println("hello from a")
}
user#user:~/p/go/test/so-multipack$ go run main.go
hello from a
user#user:~/p/go/test/so-multipack$ go build
user#user:~/p/go/test/so-multipack$ ls
a main.go so-multipack
user#user:~/p/go/test/so-multipack$
Useful link:
go build vs go build file.go
You cannot have two packages per directory, hence the error. So the solution as #Larry Battle said to move your myproject.go to a new directory.
From How to write go code
Go code must be kept inside a workspace. A workspace is a directory
hierarchy with three directories at its root:
src contains Go source files organized into packages (one package per directory),
pkg contains package objects, and
bin contains executable commands.
In most cases, no. However, there is an exception for unit tests.
Working Example:
Here are 2 different packages (mypackage and mypackage_test) in 1 directory (mypackage). The compiler will not complain about this.
mypackage folder:
mypackage/
foo.go
foo_test.go
mypackage/foo.go:
package mypackage
func Add(a int, b int) int {
return a + b
}
mypackage/foo_test.go:
package mypackage_test
// Unit tests...
Rules:
The 2 packages must have the following names:
NameOfDirectory.
NameOfDirectory + _test.
The names of the files in the _test package must end with _test.go
If you're receiving a confusing compiler error along the lines of found packages "foo" and "bar", you've probably broken one or more of these rules.
You can't have two golang files in one directory with two packages. So you need to move main.go out of myproject.
the directory structure before move
whatever.io/
go.mod
myproject/
main.go
myproject.go
After move
whatever.io/
go.mod
main.go
myproject/
myproject.go
And you need to change your main.go's import path. If the module name is aaa
Before
import "aaa"
Need change to this
import "aaa/myproject"

Resources