function call difference between go build and go run - go

I'm new to Golang and I'm trying out a few examples as part of my learning. I have 2 Go source files - hello.go and consts.go in my example. consts.go contains some constants which are used by the functions defined in hello.go. When I build both the source files like so:
go build consts.go hello.go and run the output ./hello
the function arrayDemo() is not called at all.
However, when I just run the file hello.go using go run hello.go, the function arrayDemo() is called.
What is the difference in both the approaches that's causing the function not to be called when building?
Here's the code for hello.go:
package main
import (
"fmt"
"os"
"strconv"
"strings"
)
func main() {
fmt.Printf("Speed is %f\n", computeSpeed(54.3, 3.4))
fmt.Printf("%d\n", arrayDemo())
}
func arrayDemo() int32 {
fmt.Println("in arrayDemo")
return 5
}
Code for consts.go:
package main
// Speed speed of a vehicle
type Speed float32
func computeSpeed(dist float32, t float32) Speed {
return Speed(dist / t)
}

go run works because go run works based on file names, but go build works based on package names.
also
go help build says:
When compiling multiple packages or a single non-main package, build
compiles the packages but discards the resulting object, serving only
as a check that the packages can be built.
to my understanding this means you can not have multiple files in the main package and then get working executable by using go build

Related

Golang 1.18 - Exclude package for specific platform

I spent the whole day trying to apply a build constraint in my code:
I have an agent that is designed to work on Windows and Linux, however, I have to interact with the Windows registry (which obviously doesn't have any equivalent on Linux).
My package imports
"golang.org/x/sys/windows/registry"
The project builds on Windows but not on Linux.
I then learnt about build constraints: //go:build windows (or !linux)
I initially started with // +build windows but I saw that it's for older Go versions.
Here is the header of my package file:
//go:build windows
package utils
import (
"fmt"
"log"
"golang.org/x/sys/windows/registry"
)
...
I use VSCode both on Windows and Linux, I can also see a reference to in my go.mod file.
Any help with this please?
When I run the code above, I still get the following on Linux:
build golang.org/x/sys/windows/registry: cannot load
golang.org/x/sys/windows/registry: no Go source files (exit status 1)
Edit: I use the default VSCode tools to compile and run my project, however I have tried: go build . and I still get the same error.
Also, the _windows.go and _linux.go suffixes are not appropriate as the agent would be fore Mac in the future.
I couldn't write the entire thing in the comments but let me know if this small sample helps you:
utils_darwin.go:
package utils
import "fmt"
func Test() {
fmt.Println("Test from mac")
}
utils_linux.go
package utils
import "fmt"
func Test() {
fmt.Println("Test from linux")
}
utils_windows.go
package utils
import "fmt"
func Test() {
fmt.Println("Test from windows")
}
main.go
package main
import "github.com/ninadingole/go-dev-stuff/platform/utils"
func main() {
utils.Test()
}
When I compile the binary on mac and run it like:
GOOS=darwin go build -o prog ./platform
./prog
Test from mac
I tried to build the binary in docker for linux and got the below output
Test from linux
Let me know if this works for you otherwise I will delete the answer :D

Difference between go run ./path/dir and go run path/dir

Note: This is not asking Why the functions defined in other "main" packages are not recognised?.
I've got a project with the following structure:
go/src/github.com/me/project/cmd/web/main.go
# main.go
package main
import(
"github.com/me/myproject/internal/myproject"
)
void main() {
// ...
}
go/src/github.com/me/project/cmd/web/handlers.go
# handlers.go
package main
void someFunc() {
// ...
}
And I compile and run successfully with:
go run ./cmd/web
I can also run successfully with go run cmd/web/*.go
However, when I try to run with go run cmd/web, why does compilation fail with the output:
package cmd/web: package cmd/web is not in GOROOT (/usr/local/go/src/cmd/web)
Why does ./cmd/web work, but cmd/web does not?
When you run ./cmd/web, you refer to the correct directory in your current directory tree.
cmd/web however refers to a package living where the stdlib packages are. If you try to run this example
go run net/http
It will tell you that it can't run it because its not a main package. It has found the stdlib net/http package with that name; but since cmd/web doesn't exist it doesn't work

Struct from the same parent folder as main is not visible

I have a small go demo project in Gogland with the structure:
awsomeProject
->src
->awsomeProject
->configuration.go
->main.go
Configuration file has a simple structure just for demo:
configuration.go:
package main
type Config struct {
Data int
}
Main file just uses the Config struct:
main.go
package main
import "fmt"
func main(){
var cfg Config
cfg.Data = 1
fmt.Println("lalala")
}
The error that I have is:
/usr/local/go/bin/go run /Users/lapetre/Work/awsomeProject/src/awsomeProject/main.go
command-line-arguments
src/awsomeProject/main.go:6: undefined: Config
Process finished with exit code 2
Any idea why the Config is not seen in main?
Thanks
When you build reusable pieces of code, you will develop a package as a shared library. But when you develop executable programs, you will use the package “main” for making the package as an executable program. The package “main” tells the Go compiler that the package should compile as an executable program instead of a shared library. The main function in the package “main” will be the entry point of our executable program.
That's why you should use the following structure:
awsomeProject
->src
->awsomeProject
->configuration.go
->main.go
with main.go
package main
import "fmt"
func main(){
var cfg awsomeProject.Config
cfg.Data = 1
fmt.Println("lalala")
}
and configuration.go
package awsomeProject
type Config struct {
Data int
}
For more details:
https://golang.org/doc/code.html
https://thenewstack.io/understanding-golang-packages
How are you calling go run? If you're calling it like
go run main.go
then that's the problem.
Go run only runs the file(s) you tell it to. So you need to tell it to also run configuration.go, or if you have several go files to run you can use
go run *.go
as eXMoor suggested.
There are some limits/drawbacks to "go run *.go" however, so the better alternative is to use go build instead of go run.
go build
Will compile everything. Then, to run the executable:
./awesomeProject
To combine all of this into one command that will compile and run whatever app you're working on, you can use:
go build && ./${PWD##*/}
I have it aliased to
gorunapp
just to make it easier.
This may not actually be the answer to the problem you're having, but hopefully you'll find it useful information regardless.
Try to run your application with command:
go run *.go

Is main.go required in a Go project?

Without a background in C and only "beginner" experience in Go I'm trying to work out whether main.go is actually required or is just a convention.
I'm looking to create a simple web API but could someone clarify this for me?
main.go as a file is not required.
However, a main package with a func main() is required for executables.
Your file name can be called whatever you want.
E.g
myawesomeapp.go
package main
func main() {
fmt.Println("Hello World")
}
Running go run myawesomeapp.go will work as expected.
For a web server (an executable) you need to have a package main with a func main(), but it doesn't need to be called main.go - the file name can be anything you want it to be. From the language spec:
Program execution
A complete program is created by linking a single, unimported package
called the main package with all the packages it imports,
transitively. The main package must have package name main and declare
a function main that takes no arguments and returns no value.
func main() { … }
Program execution begins by initializing the main package and then
invoking the function main. When that function invocation returns, the
program exits. It does not wait for other (non-main) goroutines to
complete.

How to use multiple .go files in the same application

Good Morning All,
I am new to Golang. I want to move some of my functions out into separate files so that I will not have like a 10,000 line .go file at the end. lol. I created two files both have the same package called main. Do I need to change package name to be app specific? Anyway how do I get these two files to talk?
Example:
MainFile.go:
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello World!")
Test()
}
NewFile.go:
package main
import (
"fmt"
)
func Test() {
fmt.Println("Hello World Again!")
}
The test method is in the second file but cannot be reached by the first. I am sure this is some rudimentary thing I am missing.
Thanks
Update:
I tried specifying this on the command line: go build MainFile.go NewSourceFile.go. It comes back with no errors but never builds the binary. How do I get it to output the binary now?
If you run go run MainFile.go, Test() won't be found because its not in that file. You have to build the package then run the package:
Inside the folder where the 2 files are, run go build and you will get a binary in that folder. Then just run the binary: ./MyPackage

Resources