Here, I will take a very different approach to how to run your first Go program and along the clarify your confusion about
so here's my answer to — hopefully — help clarify a few moments I was confused about regarding the naming of packages and modules in Go (I will use deliberately unusual names for the files and folders so you could see that you don't have to name your files a specific way for your Go project to work (you have to structure them in a specific way though)):
So, Golang project conceptually has:
This is optional for a Go project
"Repository" — a place in a version control system where the source code for a project is stored (usually some remote repo).
This is required for a Go project to compile
"Module" — this name, conceptually, in a Go project, is used to specify the program/library as a whole (meaning, it refers to its root, which is usually stored in some remote repository).
"Packages" — in a Go project, this name is applied to literal folders within which the "package files" are stored — It's a way of organizing code within a module.
In practice, the concepts from above imply that if you want to create a multi-package project, for it to compile, you need to do the following:
Step by step example
Create a folder that will serve as a root folder for the project and cd into it
$ mkdir some_amazing_project && cd some_amazing_project
A collection of Go code becomes a module when there's a valid go.mod file in its root directory, so use the following command to generate it
go mod init my_amazing_module_lib_program
The inside of your go.mod file looks like this
module my_amazing_module_lib_program // this is your unique module identifier and you use this name as a relative root for your package names when you use "import"
go 1.19
Now create an entry point to your Go program which is a go file that should be placed in the root folder (where the go.mod file resides), but you could just as well place it in any subfolder within this module (the root folder), but no deeper than that (or you'll receive the "no Go files in <absolute_path>/some_amazing_project/some_subfolder/another_folder" error):
$ touch some_main_file.go
you can call this file whatever you want, but the convention is "main.go"
Inside of that main file you must specify the package to be main and you must have a function within that file that is also called main:
// some_main_file.go
package main
import "fmt"
func main() {
fmt.Println("hello there")
}
This is your project structure so far
some_amazing_project/
|- go.mod
|- some_main_file.go
Now, let's say you want to create a package within this module/program/library. You would need to do the following
Create a new folder, call it "amazing_package
" and create any .go file in it (the name of the file doesn't really matter as only the name of the containing folder is used to refer to the package from other .go files
$ mkdir amazing_package && cd amazing_package && touch whatever_file.go
Inside of the whatever_file.go you use the package keyword to specify the name of this package (this package name will be used only when specifying the name of the function to invoke from within other .go files — you'll see in a bit
// whatever_file.go
package wowow
import "fmt"
func PrintWowow() {
fmt.Println("this is from wowow package")
}
The variables/constants/functions/types/etc..(any "identifier" in Go) that starts with an uppercase letter is exported and is made available to be imported into other packages.
For the sake of example, let's create another file inside of this package
$ touch another_cool_file.go
Inside of the another_cool_file.go you use the same package keyword to specify the name of this package as you've used for in the whatever_file.go (because these files are in the same "package" conceptually, meaning that in practice they are stored in the same folder (if you use a different name for the package keyword while storing the file in the same folder, you'll receive an error during compilation))
// another_cool_file.go
package wowow
import "fmt"
var Some_var = 42 // this will also be automatically exported
func PrintAnotherWow() {
fmt.Println("this is also from wowow package, but from a different file")
}
This is your project structure so far
some_amazing_project/
|- go.mod
|- some_main_file.go
|- amazing_package/
|- whatever_file.go
|- another_cool_file.go
Now, to reference the "PrintWowow" and "PrintAnotherWow" function from ANY other .go file within this entire module you use the unique module identifier from go.mod file and a path relative to that identifier that specifies the location of a package folder to import (I'll use the some_main_file.go in this example. We re-write it like so)
// some_main_file.go
package main
import (
"fmt"
"my_amazing_module_lib_program/amazing_package"
)
func main() {
fmt.Println("hello there")
// now you use the name of the package specified inside of those files from *amazing_package* folder
wowow.PrintWowow()
wowow.PrintAnotherWow()
fmt.Println("and this is Some_var from the same imported package:", wowow.Some_var)
}
And here is the result of running go build . && go run .
while inside of my_amazing_module_lib_program (root) folder
hello there
this is from wowow package
this is also from wowow package, but from a different file
and this is Some_var from the same imported package: 42