I'm trying to use //go:generate to run an external tool before compiling my code, and as I need to pass a certain number of parameters, the line becomes rather long.
It seems that there is no way to write a multiline go:generate command, is it correct? Are there alternative approaches?
Thanks
There is no way to split go generate command into several lines, but there are some tips.
If you need to run multiple short commands you can write them one by one like the following.
//go:generate echo command A
//go:generate echo command B
//go:generate ls
You also should know that there is not a bash script but a raw command. So the following works not as one may expect.
//go:generate echo something | tr a-z A-Z > into_file
// result in "something | tr a-z A-Z > into_file"
For long or complex commands you should use separate script (or maybe go program) that is called from go:generate comment.
//go:generate sh generate.sh
//go:generate go run generator.go arg-A arg-B
In generator.go you should use build tag to prevent it from normal compilation with other files.
// +build ignore
package main
// ...
The best place to learn go is go sources: https://github.com/golang/go/blob/master/src/runtime/runtime.go#L13
This is far from an ideal solution, but you could use a directive of the form
//go:generate -command <alias> <command-with-parameters>
The directive above specifies, for the remainder of the current source file only, that <alias> is equivalent to the command <command-with-parameters>.
This method might be useful in your case since you mentioned that you needed to pass a certain number of parameters (I'm assuming lots). You could potentially use it to emulate a single line break. I say single because nested aliases don't work (at least right now).
An example:
//go:generate BAKE "ramen"
// The above go:generate directive does NOT work, unless:
// - You somehow have bake on your path.
// - You did a `//go:generate -command BAKE ...`
/* Now, assuming you have a command `kitchen-tools` with lots of possible parameters... */
//go:generate -command BAKE kitchen-tools -appliance=sun -temp=5800K -time=1ns
//go:generate BAKE -panic=if-burnt -safety=fire_extinguisher,mitts "fresh pizza"
// The previous //go:generate line runs the following command:
// kitchen-tools -appliance=sun -temp=5800K -time=1ns -panic=always -safety=fire_extinguisher,mitts "fresh pizza"
/* BAKE can be used as many times as necessary for the rest of the file. For instance... */
//go:generate BAKE -no-return -unsafe "grand piano"
Furthermore, I suggest you use the build tag generate (rather than something like ignore) since the go generate tool sets the build tag generate when it examines your files:
// +build generate
package main
// ...
Related
I have a set of text files and a set of GoLang files. The GoLang files contain directives such as the following:
//go:embed hello.txt
var s string
I want to write a bash script which takes the above code and substitutes the following in its place:
var s string = "<contents of hello.txt>"
Specifically, I want to bash script to go through all GoLang source files and replace all go:embed/string declaration pairs with a string defined to be the contents of the file specified in the embed directive.
I'm wondering if there is an existing program which can be configured to do the above. Otherwise, I'm planning on writing the algorithm myself.
Further explaination:
I am trying to replicate GoLang's embed directive (https://tip.golang.org/pkg/embed/).
We are not yet on GoLang 1.16, so we cannot use this functionality, but we are replicating it as closely as possible so that moving over to the standard implementation is as painless as possible.
Below is an attempt at solving your problem:
for i in file1 file2; do
awk '/^\/\/go:embed /{f=$2;next}/^var/&&f{printf"%s = \"",$0;system("cat "f);print"\"";f=0;next}1' < "$i" > "$i.new"
done
The awk script prints all normal lines, only if it encounters the embed directive this line will be skipped (and the file name remembered in variable f). A subsequent line starting with var will then be extended by the content of the file with the remembered name (using the system call "cat").
Beware, there are no error checks at all, no attempt to fix quotes and whatever. So for practical use - unless the file contents you are about to embed are known to be good-natured - you probably have to take a more sophisticated approach.
Is there a way to run multiple C program through one single C source code file using command line argument?
E.g. suppose the executable file is named, testing.out, if in the runtime one wants
the first test, then type “Testing.out 1”, if the second, “Testing.out 2”,
etc.
Yes, this can be easily done using the command line arguments functionality provided by C.
You can read more about it here: https://www.tutorialspoint.com/cprogramming/c_command_line_arguments.htm
And a lots of other tutorials:
https://www.geeksforgeeks.org/command-line-arguments-in-c-cpp/
https://www.cprogramming.com/tutorial/c/lesson14.html
With go test -v pattern I can select and only run the tests that matches a pattern, but is there any way that I can list all test cases without run them. There is this case that the project just handed over to me has a lot of test case and I need to select some tests to run. I know greping the sources xxx_test.go is a way but is there more elegant way? I mean, each test has its meta data stored in some where, right? as the tests are required to be in a specific signature(func TestXXX(*testing.T)). This meta data can be used to do this kind of work.
Just saw this in the Go1.9 release notes (draft) and I think could be what you are looking for
The go test command accepts a new -list flag, which takes a regular
expression as an argument and prints to stdout the name of any tests,
benchmarks, or examples that match it, without running them.
There's no saved metadata, grepping is the only way pretty much.
If you have ack, you can easily use something like this:
➜ ack 'func Test[^(]+'
If you do not use ack as another answer mentions, you may simply grep -r "func Test" . | wc -l. This works because
grep for substring func Test, which should include every test func (it also includes TestMain)
flag -r tells grep to look in subdirectories recursively
wc -l will count the number of lines piped into it, which should be the number of test cases
I'm trying to do a gofmt rewrite of all packages that start with a certain prefix. Something like:
gofmt -r 'github.com/some/path/<wildcard> -> someotherrepo.com/some/path/<wildcard>'
Obviously wildcard isn't valid syntax, just showing the concept. I've tried with a single lowercase character, but that doesn't work here.
Is it possible to do what I'm trying with gofmt?
This is what the gofmt command page says
Given a file, it operates on that file; given a directory, it operates on all .go files
in that directory, recursively
https://golang.org/cmd/gofmt/
I have a go generate directive which looks like this:
//go:generate myprog -someName thisname -data 'Request: Typ "." callMe, Rsp: MyTyp "." close'
The issue is that the program receives only value of -someName flag ("thisname"). I assume the -data flag is discarded for some reasons. Any idea why? It's working if I execute the program directly from command line so I guess it's a go specific issue.
From the design document of go generate https://docs.google.com/document/d/1V03LUfjSADDooDMhe-_K59EgpTEm3V8uvQRuNMAEnjg/edit:
The arguments are space-separated tokens (or double-quoted strings) passed to the generator as individual arguments when it is run.
So if you want to pass an argument containing space you will have to double quote them. You used single quotes which works in your shell but not with go generate