How to stop Go 1.11 from building quicktemplate .qtpl files? - go

I have some Go packages that use quicktemplate. Quicktemplate compiles template files with the .qtpl extension to Go files with the .qtpl.go extension using the qtc CLI app. In Go versions prior to 1.11, having .qtpl files in a Go package wasn't a problem as the .qtpl files would be ignored by the compiler. However, Go 1.11 appears to process .qtpl files, causing compilation failures.
An example that works with Go 1.3-1.10 but not 1.11 is available here and described below.
Source: https://github.com/grokify/gocharts/tree/master/charts/c3
Build Logs: https://travis-ci.org/grokify/gocharts/builds/431794367 (Go 1.0-1.11)
The package directory contains:
timeseries_page.qtpl template file
timeseries_page.qtpl.go template file compiled to Go using qtc
Previously, only the file ending in .go would be compiled and everything builds fine. With 1.11, there is an error thrown while parsing the .qtpl file which isn't intended to be built by the Go compiler.
Here is a minimal Go program using that package will fail to build in Go 1.11, but work with 1.10.
package main
import (
"github.com/grokify/gocharts/charts/c3"
)
func main() {
_ = c3.C3Chart{}
}
Here's the error showing the timeseries_page.qtpl file:
$ go build main.go
# github.com/grokify/gocharts/charts/c3
timeseries_page.qtpl:42: undefined: TimeseriesHTML
timeseries_page.qtpl:48: undefined: TimeseriesHTML
TimeseriesHTML is a function that is called in that template file and built by another quicktemplate file in the timeseries_js.qtpl.go file.
The same result and output is encountered with the following:
$ go run main.go
$ go test main.go
Is there a way to get back the prior Go behavior, or ignore .qtpl files during builds?

Related

go build: no Go files in /msfs2020-go-master

Im trying to rebuild a golang github repository to apply some minor changes.
The go application Im trying to modify is the following https://github.com/lian/msfs2020-go
Please use the provided github link to inspect the file tree.
I used the master branch and extracted it to /user/Documents/msfs2020-go-master
If I call go build from /user/Documents/msfs2020-go-master the output equals: no Go files in /user/Documents/msfs2020-go-master
I tried deleting the go.mod and recreating it with go mod init github.com/lian/msfs2020-go followed with a go mod tidy
but still no Go files in /user/Documents/msfs2020-go-master
Here the current go.mod
module github.com/lian/msfs2020-go
go 1.16
require github.com/gorilla/websocket v1.4.2
And here the go.sum
github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc=
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
The master was build with 1.14 and Im using 1.16 golang.
All my test go applications/modules run/build/install fine at a "Hello World" developing level.
What did I do wrong? I gladly accept any input and will provide additional information's if requested.
The command go build builds the package in the current working directory. The command reports an error because there is not a package at the root of the repository.
Fix by building the package containing the command. Any of the following will work from the root of the repository:
go build ./vfrmap
or
cd vrfrmap
go build
or
go build github.com/lian/msfs2020-go/vfrmap
See also the file build-vfrmap.sh.

command-line-arguments : handling "undefined" error message

Following is how the source files are organized
✘-1 ~/Go/src/github.com/krmahadevan/packages
18:24 $ tree .
.
├── sample_main.go
└── sample_one.go
0 directories, 2 files
Here's how the source code looks like:
sample_one.go
package main
var data map[string]string
func init() {
data = make(map[string]string, 0)
}
sample_main.go
package main
import "fmt"
func main() {
data["foo"] = "bar"
fmt.Println(data)
}
Now when I attempt at running sample_main.go I get errors stating that data is undefined.
18:24 $ go run sample_main.go
# command-line-arguments
./sample_main.go:6:2: undefined: data
./sample_main.go:7:14: undefined: data
✘-2 ~/Go/src/github.com/krmahadevan/packages
But when I build the code into a binary and then execute it, it runs fine.
✔ ~/Go/src/github.com/krmahadevan/packages
18:27 $ go build
✔ ~/Go/src/github.com/krmahadevan/packages
18:28 $ ./packages
map[foo:bar]
✔ ~/Go/src/github.com/krmahadevan/packages
I would like to understand why is this behavior ?
Environment:
18:31 $ go version
go version go1.11.4 darwin/amd64
The closest I found was this post : Golang : command-line-arguments undefined: variable
But this post talks about scoped variables that are defined in main.
But my problem statement involves variables defined in another go file and accessed in the main method.
To understand why, read the go command documentation:
Command go
Compile and run Go program
Usage:
go run [build flags] [-exec xprog] package [arguments...]
Run compiles and runs the named main Go package. Typically the package
is specified as a list of .go source files, but it may also be an
import path, file system path, or pattern matching a single known
package, as in 'go run .' or 'go run my/cmd'.
Compile packages and dependencies
Usage:
go build [-o output] [-i] [build flags] [packages]
Build compiles the packages named by the import paths, along with
their dependencies, but it does not install the results.
If the arguments to build are a list of .go files, build treats them
as a list of source files specifying a single package.
For more about specifying packages, see 'go help packages'. For more
about where packages and binaries are installed, run 'go help gopath'.
go run: Typically the package is specified as a list of .go source files.
For your go run example, list the files:
go run sample_main.go sample_one.go
To fix it, just run the following command:
Windows: go run * or go build *
Unix: go run . or go build .
You are going to run it inside the folder of the files you want to use.

What is the use of pkg directory in Go?

If we have bin directory already where executables go then what is the need of pkg directory? Please explain.
The pkg directory contains Go package objects compiled from src directory Go source code packages, which are then used, at link time, to create the complete Go executable binary in the bin directory.
We can compile a package once, but link that object into many executables. For example, the fmt package appears in almost every Go program. It's compiled once but linked many times, a big saving.
~/go/pkg
From How to Write Go Code, we know ~/go/pkg can store third party library. For example:
Create two file main.go and go.mod:
//main.go
package main
import (
"fmt"
"github.com/google/go-cmp/cmp"
)
func main() {
fmt.Println(cmp.Diff("Hello World", "Hello Go"))
}
//go.mod
module example.com/user/hello
go 1.13
Install a third party library
$ ls ~/go/pkg/mod/github.com/google/
...
$ go install example.com/user/hello
go: finding github.com/google/go-cmp v0.5.2
go: downloading github.com/google/go-cmp v0.5.2
go: extracting github.com/google/go-cmp v0.5.2
$ ls ~/go/pkg/mod/github.com/google/
... go-cmp#v0.5.2
$ ls ~/go/pkg/mod/github.com/google/go-cmp#v0.5.2
And then, you will see a lot of go files, not compile files.
$ ls ~/go/pkg/mod/github.com/google/go-cmp#v0.5.2/cmp/
... example_test.go options.go ...
pkg in user project
This pkg is a directory/package of user project. You can see it as Library and it's OK to use by external applications. For more things, you can check here.
You put your source code in src directory while pkg is the directory that holds compilation output of your actual source code. If you use multiple libraries/packages you will have different output with extension .a for each one, A linker should be responsible for linking and combining all of them together to produce one final executable in bin directory.
As pkg and bin are more specific to the machine or operating system into which you build your actual source code so it is not recommended to share both of them, your repo should have only your actual code.
A side note, if you plan to use docker containers, pkg dir should be ignored as we may build the source code in windows for example while you import/mount your code into linux container; at this time pkg will have compiled files that are only valid for windows

Go: How does go run file.go work

The commands go build and go install compile the files into binaries. Does go run compile or interpret the file? I couldn't find explanations online and may have missed it. Appreciate pointers. Thanks!
It's more or less the equivalent of running go build X.go -o /tmp/random-tmp-folder/exe && /tmp/random-tmp-folder/exe
The go run command compiles and runs a main package comprised of the .go files specified on the command line. The command is compiled to a temporary folder.
The go build and go install examine the files in the directory to determine which .go files are included in the main package.
Command go run performs project's building under the hood (so yes it builds project)
and with flag --work (go run --work main.go) you can see the location of temporary build files.
Also in official documentation (go1.11) you can find:
go run - compiles and runs the named main Go package.
go build - compiles the packages named by the import paths,
along with their dependencies, but it does not install the results.
go install - compiles and installs the packages named by the import paths.
Unlike in java, where the bytcode is created and interpreted at the execution time, go creates an executable file that is dependent on the machine being used,like in c, c++.

How to compile Go program consisting of multiple files?

I have a small program that consists of three files, all belonging to the same package (main). But when I do go build main.go the build doesn't succeed. When it was just one file (main.go), everything worked fine.
Now that I took some effort to separate the code, it looks like the compiler is unable to find the stuff that was taken out of main.go and put into these two other files (that reside in the same directory as the main.go). Which results in undefined 'type' errors.
How to compile this program that consists of multiple files?
New Way (Recommended):
Please take a look at this answer.
Old Way:
Supposing you're writing a program called myprog :
Put all your files in a directory like this
myproject/go/src/myprog/xxx.go
Then add myproject/go to GOPATH
And run
go install myprog
This way you'll be able to add other packages and programs in myproject/go/src if you want.
Reference : http://golang.org/doc/code.html
(this doc is always missed by newcomers, and often ill-understood at first. It should receive the greatest attention of the Go team IMO)
When you separate code from main.go into for example more.go, you simply pass that file to go build/go run/go install as well.
So if you previously ran
go build main.go
you now simply
go build main.go more.go
As further information:
go build --help
states:
If the arguments are a list of .go files,
build treats them as a list of source files specifying a single package.
Notice that go build and go install differ from go run in that the first two state to expect package names as arguments, while the latter expects go files. However, the first two will also accept go files as go install does.
If you are wondering: build will just build the packages/files, install will produce object and binary files in your GOPATH, and run will compile and run your program.
Since Go 1.11+, GOPATH is no longer recommended, the new way is using Go Modules.
Say you're writing a program called simple:
Create a directory:
mkdir simple
cd simple
Create a new module:
go mod init github.com/username/simple
# Here, the module name is: github.com/username/simple.
# You're free to choose any module name.
# It doesn't matter as long as it's unique.
# It's better to be a URL: so it can be go-gettable.
Put all your files in that directory.
Finally, run:
go run .
Alternatively, you can create an executable program by building it:
go build .
# then:
./simple # if you're on xnix
# or, just:
simple # if you're on Windows
For more information, you may read this.
Go has included support for versioned modules as proposed here since 1.11. The initial prototype vgo was announced in February 2018. In July 2018, versioned modules landed in the main Go repository.
In Go 1.14, module support is considered ready for production use, and all users are encouraged to migrate to modules from other dependency management systems.
You could also just run
go build
in your project folder myproject/go/src/myprog
Then you can just type
./myprog
to run your app
It depends on your project structure. But most straightforward is:
go build -o ./myproject ./...
then run ./myproject.
Suppose your project structure looks like this
- hello
|- main.go
then you just go to the project directory and run
go build -o ./myproject
then run ./myproject on shell.
or
# most easiest; builds and run simultaneously
go run main.go
suppose your main file is nested into a sub-directory like a cmd
- hello
|- cmd
|- main.go
then you will run
go run cmd/main.go
You can use
go build *.go
go run *.go
both will work also you may use
go build .
go run .
Yup! That's very straight forward and that's where the package strategy comes into play. there are three ways to my knowledge.
folder structure:
GOPATH/src/
github.com/
abc/
myproject/
adapter/
main.go
pkg1
pkg2
warning: adapter can contain package main only and sun directories
navigate to "adapter" folder. Run:
go build main.go
navigate to "adapter" folder. Run:
go build main.go
navigate to GOPATH/src
recognize relative path to package main, here "myproject/adapter". Run:
go build myproject/adapter
exe file will be created at the directory you are currently at.

Resources