With the following code, go vet does not show an "out of bounds" error as I would expect:
package main
func main() {
a := make([]string, 1)
a[2] = "foo"
}
From the go vet documentation:
Flag: -shift
Shifts equal to or longer than the variable's length.
If go vet is not the tool to catch these errors, what is? Compiling and/or testing the code will catch this, but I'm looking for a static analysis based tool.
Its true that Go vet is for catching suspicious runtime error, by using some heuristics. The first Para is exact regarding its work
Vet examines Go source code and reports suspicious constructs, such as Printf calls whose arguments do not align with the format string. Vet uses heuristics that do not guarantee all reports are genuine problems, but it can find errors not caught by the compilers.
also in documentation its mentioned that
Note that the tool does not check every possible problem and depends on unreliable heuristics.
also the code which you are using to check for vetting your package is something very difficult to find by those heuristics as you are using a dynamic slice which can be appended or modified at runtime.
thereby not a perfect heuristic can be thought about for that.
fmt.Printf("%d", "scsa", "DSD")
those heuristic can catch things like this it all depends on what the training data is.
So vet should be a tool to take a quick look whether there is some general mistake which has been missed by you (If It gets caught :-) )its nothing like a compile tool or runtime checker it just runs some heuristics on the plane code you have written.
also documentation provides a list of available checks some examples are
Assembly declarations,
Copying locks,
Printf family,
Methods,
Struct tags,
etc there are many, you can see and read the complete documentation
Related
This code
package main
import (
"fmt"
)
func main() {
fmt.Println("%%dude")
}
Playground link: https://play.golang.org/p/Shq5pMHg4bj
gives a go vet warning
./prog.go:8:2: Println call has possible formatting directive %d
How can I tell go vet that I really want to write two percent signs and not to warn me?
You can't really supress that, but even if you could with custom rules and flags, I wouldn't do it because someone else building your code will still run into this.
Instead you may use any of these alternatives which produce the same output without any warnings from vet:
fmt.Println("%%"+"dude")
fmt.Println("%\x25dude")
fmt.Printf("%%%%dude\n")
s := "%%dude"
fmt.Println(s)
Try the examples on the Go Playground.
You can't really (apart from not writing that code). Go vet doesn't have any mechanism for "I really meant this" comments to suppress warnings. There have been several discussions about it in the past five years, none of which have resulted in any action. You just have to accept what the help text says: go vet "uses heuristics that do not guarantee all reports are genuine problems".
I mostly use constants for documentation purposes e.g. a useful variable name or when I repeat certain sequences of strings over and over and don't want to change them manually. But I was wondering whether there's any performance difference. Am I right in my assumptions that there's no runtime difference between a literal and a constant, since constants are replaced at runtime?
Maybe I am misunderstanding, but I didn't find anything that tells me that this is wrong. The Go Tour doesn't provide any valuable information on and nor did the Constants blog post.
There's nothing that says one way or another whether even this trivial program:
package main
func main() {}
might run fast as lightning when compiled on a Tuesday, but slow as molasses when compiled on a late Friday afternoon. (Perhaps the Go compiler is anxious to head home for a beer and a weekend off and produced terrible code on Friday afternoon.1)
That said, if you're comparing, e.g.:
package main
import (
"fmt"
)
const hello = "hello"
var playground = "playground"
func main() {
fmt.Printf("%s, %s\n", hello, playground)
}
we might note that in the const variant (hello), the compiler is forced to know at compile time that the string literal "hello" is a string literal, while in the var variant (playground), the compiler could be lazy and assume that the variable playground might be modified in some other function. This in turn, combined with the ability of the compiler to know that fmt.Println is a particular function—the way GCC inserts special knowledge of the C printf function, for instance—could allow the compiler to more easily compile this to:
fmt.Printf("hello, %s\n", playground)
where only one runtime reflect happens, in case the variable playground has changed. But the existing Go compilers use SSA (see also https://golang.org/pkg/cmd/compile/internal/ssa/) and there are no writes to the variable, so we can expect simple (and usually simple = fast) runtime code here.
Playing with the Godbolt compiler site, it seems that when using const, the current compiler actually has to insert one conversion to string. The var version winds up with less runtime code. I didn't test it with string literals inserted. The %s directives are never expanded in line, but fmt.Printf really calls fmt.Fprintf directly, with os.Stdout as the first argument.
Overall, you're usually best off writing the clearest code you can. Then, if it's too slow (for whatever definition you have of "too slow"), measure. I'm guilty of overdoing my coding-time optimization myself, though. :-)
1Don't anthropomorphize computers. They hate that!
Disclaimer: yes I know that this is not "supposed to be done" and "use interface composition and delegation" and "the authors of the language know better". However, I am confronted with a choice of either copy-pasting from the standard library and creating my own packages, or doing what I am asking. So please do not reply with "What you want to do is wrong, you are a bad dev and you should feel bad."
So, in Go we have the http stdlib package. This package has a number of functions for dealing with HTTP Range headers and responses (parsers, a struct for "offset+size" and so forth). For various reasons I want to use something that is very similar to ServeContent but works a bit differently (long story short - the amount of plumbing needed to do the ReaderAt gymnastics is suboptimal for what I want to accomplish) so I want to parse the HTTP Range header myself, using the utility functions/structs from the http stdlib package and then deal with them manually. Basically, I want a changed version of ServeContent :-)
Is there a way for me to "reopen" the http stdlib package to use it's unexported identifiers? ABI is not a concern for me as the source is mine, the program gets compiled from scratch every time etc. etc. and it does not need binary compatibility with older/other Go versions. I.e. I am able to ensure that the build is going to be done on a specific Go version and there are tests to check that an unexported identifier disappeared. So...
If there is a package called foo in the Go standard library, but it only exposes a MagicMegamethod that does the thing I do not need, and uses usefulFunc and usefulStruct that I want to get access to, is there a way for me to get access to those identifiers? Either by reopening the package, or using some other way... that does not involve copy-pasting dozens of lines from stdlib without tests etc.
There exist (rather gruesome) ways of accessing unexported symbols, but it requires nontrivial amounts of tricky code, so there's unlikely to be a net win.
Since you've outruled the "don't do this" direction, it seems that the answer is either NO or use the methods described in the post I linked to (and this repo).
FWIW I'd personally just copy the code I need from the standard library and tweak it to my needs. This would likely take less time than the time it took you to write this SO question :-)
Where in Go's source code can I find their implementation of make.
Turns out the "code search" functionality is almost useless for such a central feature of the language, and I have no good way to determine if I should be searching for a C function, a Go function, or what.
Also in the future how do I figure out this sort of thing without resorting to asking here? (i.e.: teach me to fish)
EDIT
P.S. I already found http://golang.org/pkg/builtin/#make, but that, unlike the rest of the go packages, doesn't include a link to the source, presumably because it's somewhere deep in compiler-land.
There is no make() as such. Simply put, this is happening:
go code: make(chan int)
symbol substitution: OMAKE
symbol typechecking: OMAKECHAN
code generation: runtime·makechan
gc, which is a go flavoured C parser, parses the make call according to context (for easier type checking).
This conversion is done in cmd/compile/internal/gc/typecheck.go.
After that, depending on what symbol there is (e.g., OMAKECHAN for make(chan ...)),
the appropriate runtime call is substituted in cmd/compile/internal/gc/walk.go. In case of OMAKECHAN this would be makechan64 or makechan.
Finally, when running the code, said substituted function in pkg/runtime is called.
How do you find this
I tend to find such things mostly by imagining in which stage of the process this
particular thing may happen. In case of make, with the knowledge that there's no
definition of make in pkg/runtime (the most basic package), it has to be on compiler level
and is likely to be substituted to something else.
You then have to search the various compiler stages (gc, *g, *l) and in time you'll find
the definitions.
As a matter of fact make is a combination of different functions, implemented in Go, in the runtime.
makeslice for e.g. make([]int, 10)
makemap for e.g. make(map[string]int)
makechan for e.g. make(chan int)
The same applies for the other built-ins like append and copy.
It seems that GO language does not have warnings in it. I've observed
few instances.
1. "declared and not used"(if variable is declared and not used
anywhere it gives an error and does not compile the program)
2. "imported and not used"(similarly if package is imported and not
used anywhere it gives an error and does not compile the program)
Can somebody help. If they have any pointers.
Go is trying to prevent this situation:
The boy is smoking and leaving smoke rings into the air. The girl gets
irritated with the smoke and says to her lover: "Can't you see the
warning written on the cigarettes packet, smoking is injurious to
health!"
The boy replies back: "Darling, I am a programmer. We don't worry
about warnings, we only worry about errors."
Basically, Go just wont let you get away with unused variables and unused imports and other stuff that is normally a warning on other languages. It helps put you in a good habit.
The Go Programming Language
FAQ
Can I stop these complaints about my unused variable/import?
The presence of an unused variable may indicate a bug, while unused
imports just slow down compilation. Accumulate enough unused imports
in your code tree and things can get very slow. For these reasons, Go
allows neither.
When developing code, it's common to create these situations
temporarily and it can be annoying to have to edit them out before the
program will compile.
Some have asked for a compiler option to turn those checks off or at
least reduce them to warnings. Such an option has not been added,
though, because compiler options should not affect the semantics of
the language and because the Go compiler does not report warnings,
only errors that prevent compilation.
There are two reasons for having no warnings. First, if it's worth
complaining about, it's worth fixing in the code. (And if it's not
worth fixing, it's not worth mentioning.) Second, having the compiler
generate warnings encourages the implementation to warn about weak
cases that can make compilation noisy, masking real errors that should
be fixed.
It's easy to address the situation, though. Use the blank identifier
to let unused things persist while you're developing.
import "unused"
// This declaration marks the import as used by referencing an
// item from the package.
var _ = unused.Item // TODO: Delete before committing!
func main() {
debugData := debug.Profile()
_ = debugData // Used only during debugging.
....
}
One solution for unused imports is to use goimports, which is a fork of gofmt. It automatically adds missing imports and removes unused ones (in addition to formatting your code).
http://godoc.org/code.google.com/p/go.tools/cmd/goimports
I've configured my editor to automatically run goimports whenever I save my code. I can't imagine writing go code without it now.
From what I just read, (wikipedia)
"Go's syntax includes changes from C aimed at keeping code concise and readable."
The word "concise" is very important to the compiler. I have found out
that the syntax enforced by the compiler is no longer "\n" or whitespace
agnostic. And there are no "warning" type errors.
There are good things about Go. There are some not so good things. The
attitude of no warnings is a bit extreme, especially when developing or testing
a new package. It seems that partial development is not acceptable. Warnings are not acceptable. It is either the production version or the highway. This is a very dualistic point of view. I wonder if evolution would have resulted in "life", if that had been the constraints on nature.
I can only hope that things will change. Death seems to be very beneficial at times.
I have tried Go, and I am disappointed. At my age I don't think I will return.