Golang - package name as double underscore - go

In my protobuf generated go code, the package is:
package __
What does the double underscore mean, does it means the same as folder name ?
Is there a document for this, I searched but didn't found any. And the code can compile without error.

Yes it means the same directory. Let's look at the following code.
Directory Structure
.
├── go.mod
├── greet
│ └── greet.go
└── main.go
Content in greet.go
package __
import "fmt"
func Hello(name string) {
fmt.Printf("Hello %s\n", name)
}
Content in main.go
package main
import greet "playground/greet"
func main() {
greet.Hello("Eric")
}
Current Directory
$ pwd
/Users/thedatageek/Codes/go-playground
Unfortunately I also couldn't find any docs for go.
But it seems that its kinda good thing. You really don't need to name the package. You just name the directory and the package name would be automatically the same.
Note: This is definitely not the grpc or protobuf thing. It is however a customary that if you have generated proto stub from a proto file and if you add some additional utility file you may put those into a dir and then import it directly via directory name. For example the following github repos
https://github.com/Ash110/gRPC-Logger
https://github.com/dist1ll/cache-prototype
https://github.com/kamensotirov99/int-gateway
https://github.com/rachaelyychen/go-gee
https://github.com/suvvm/ToadOCREngine
https://github.com/denyami/drawing-api

Related

Importing external functions and logic from another go file inside same directory

I am new to golang and have been loving it so far. So far I've been writing all my applications logic inside the main.go and it is starting to get quite cumbersome with so much text on the screen. I cannot for the life of me figure out how to import external functions that are located in another .go file. Here is a basic example of what I'm trying to accomplish
main.go
package main
func main() {
SayHello() //THIS IS THE FUNCTION IMPORTED FROM hello.go
{
hello.go
package hello
import "fmt"
func SayHello() {
fmt.Println("Hello!")
{
project structure
/
-main.go
-hello.go
I know this is a fairly simple question but everything I try will result in an error in my console. All I want in this example is to export the SayHello function from the hello.go file into the main.go file, and as far as I understand anything exported must start with a capital letter. The whole go.mod file and package declaration at the top if each file confuses me and I have not been able to figure this out for hours.
You can only have a single package per directory. If you want the code in hello.go to live in a separate package, you need to move it into a subdirectory.
First, this assumes that you've initialized your project using go mod init <something>. For the purposes of this example, we'll start with:
go mod init example
This creates our go.mod file. Next, we set up the correct directory structure:
.
├── go.mod
├── hello
│   └── hello.go
└── main.go
hello.go is correct as written (well, once you fix the syntax errors in your posted code). We'll need to add an import to main.go:
package main
import "example/hello"
func main() {
hello.SayHello() //THIS IS THE FUNCTION IMPORTED FROM hello.go
}
This will build an executable that produces the expected output:
$ go build
$ ./example
Hello!

How to import a single go file in golang? Unable to import go file

Trying to import a file go file but unable to do so.
I have one main file:
main/
main.go
go_single_file.go
package main
import (
"./go_single_file"
)
func main() {
}
and go_single_file:
package go_single_file
func hello() bool{
return true
}
when i try to import go_single_file in my main file i get some sort of import error.
I am doing something wrong but not sure what.
If i make a separate package and import it then it works but not if it's in same folder.
Can anyone tell how can i import a go file from same folder.
In Golang files are organized into subdirectories called packages which enables code reusability.
The naming convention for Go package is to use the name of the directory where we are putting our Go source files. Within a single folder, the package name will be same for the all source files which belong to that directory.
I would recommend you to use go modules and your folders structure should be like this.
.
├── main.go
├── go.mod
├── go_single_file
│ └── go_single_file.go
In your go_single_file.go you are not using exported names for the function hello. So your file inside the go_single_file/go_single_file.go would look like this.
package go_single_file
func Hello() bool{
return true
}
Your main file would like this
package main
import (
"module_name/go_single_file"
)
func main() {
_ = go_single_file.Hello()
}

How to go mod get local package?

I want go.mod get a folder inside the selfCheck(get package inside selfCheck folder).
selfCheck/encrypt , selfCheck/searchSchool
my screenshots is here
(don't mind vendor file. i'll remove it.)
You don't need to require a folder in the project itself in go.mod files. go.mod is only requireing external packages from other repositories.
I wrote a blogpost on starting with Go that covers this question. https://marcofranssen.nl/start-on-your-first-golang-project
I also wrote a whole bunch more articles on Go https://marcofranssen.nl/categories/golang
In summary what you should do it use the full url of your git repository so other projects can depend on it as a best practice.
e.g.
go mod init github.com/your-user/selfcheck
Once you did that your go.mod file looks like this.
module github.com/your-user/selfcheck
go 1.17
Please note camel casing is not the way you name go packages. Go packages should be all lowercase.
Now if you want to create sub packages as you are asking for you should create folders. e.g. your project could look like this.
$ tree selfcheck
selfcheck
├── go.mod
├── main.go
└── searchschool
└── searchschool.go
1 directory, 3 files
Now to reference code from the searchschool package you can do the following in main.go.
package main
require (
"fmt"
"github.com/your-user/selfcheck/searchschool"
)
func main() {
fmt.Println(searchschool.Excute())
}
Please note all functions have to start with an uppercase to access them outside of the searchschool package. E.g. searchschool/searchschool.go
package searchschool
func Execute() string {
return privateFunc() + "!"
}
func privateFunc() string {
return "Hello World"
}

Call function in another files

I don't know how I can use function in another file.
my project architecture:
.
├── main.go
└── src
└── function.go
1 directory, 2 files
main.go
package main
import "src/funcrion"
func main() {
funcrion.Display();
}
function.go
package src
import "fmt";
func Display() {
fmt.Println("Hello World");
}
For start my project I use:
go run main.go
error:
main.go:3:8: cannot find package "src/funcrion" in any of:
/usr/local/opt/go/libexec/src/src/funcrion (from $GOROOT)
/Users/clementbolin/go/src/src/funcrion (from $GOPATH)
In first, I want to resolve this problem. In second time I want to know what is the best option for compile a real project with more 10 files for example, do I need to use Makefile? Or like in Rust go has package manager?
When you do import "src/funcrion" the go compiler will try to search for this in GOPATH and GOROOT, as you see in your error message. It does not try to search in the current folder. Since it doesn't find a package with that name in either GOPATH or GOROOT, it gives you that error.
A good way to reference "the current folder" would be using go modules. On the root of your project do $ go mod init myproject. (replace myproject for a more appropriate name for your project)
After you do that, you can use "myproject" to reference the project folder in package names, like:
package main
import "myprject/src"
func main() {
src.Display();
}
Also note that the import goes only up to the package name and not the file name. So, in your case, you shouldn't do import myproject/src/function just because you have a function.go file inside a src package.
And since your Display function is inside the src package, you refer to it simply with src.Display() after importing the package. No need to specify the name of the file anywhere.
You can read more about go modules here: https://blog.golang.org/using-go-modules
Another tip is to not use src as a package name. In Go, it's common to not have a "src" folder, and as a package name is also not very good. For instance, see the line that reads src.Display(). Instinctively, i would read this as something like "the Display of the source", which has no meaning. But if instead of src you name your package text, that same line would read text.Display() which would read as "display some text", which is more accurate and meaningful to what the function is doing.
I believe the package name is src but I see you are trying to import src\funcrion There is no such package called funcrion.
I think you should just do something like this main.go
package main
import "src"
func main() {
src.Display();
}
or if you would like to call your src package as funcrion, then just import it like below,
import funcrion "src"
And make sure your file structure is as below and inside $GOPATH
Users
└── clementbolin
└── go
└── src
├── main.go
└── src
└── function.go

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.

Resources