Go language warnings and errors - go

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.

Related

Why does "go vet" not show an error here?

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

How to disable Golang unused import error

By default, Go treats unused import as error, forcing you to delete the import.
I want to know if there exists some hope to change to this behavior, e.g. reducing it to warning.
I find this problem extremely annoying, preventing me from enjoying coding in Go.
For example, I was testing some code, disabling a segment/function. Some functions from a lib is no longer used (e.g. fmt, errors, whatever), but I will need to re-enable the function after a little testing. Now the program won't compile unless I remove those imports, and a few minutes later I need to re-import the lib.
I was doing this process again and again when developing a GAE program.
Adding an underscore (_) before a package name will ignore the unused import error.
Here is an example of how you could use it:
import (
"log"
"database/sql"
_ "github.com/go-sql-driver/mysql"
)
To import a package solely for its side-effects (initialization), use
the blank identifier as explicit package name.
View more at https://golang.org/ref/spec#Import_declarations
The var _ = fmt.Printf trick is helpful here.
I have the same problem. I understand the reasoning for why they implemented the language to disallow unused imports and variables, but I personally find this feature annoying when writing my code. To get around this, I changed around my compiler to allow optional flags for allowing unused variables and imports in my code.
If you are interested, you can see this at https://github.com/dtnewman/modified_golang_compiler.
Now, I can simply run code with a command such as go run -gcflags '-unused_pkgs' test.go and it will not throw these "unused import" errors. If I leave out these flags, then it returns to the default of not allowing unused imports.
Doing this only required a few simple changes. Go purists will probably not be happy with these changes since there is good reason to not allow unused variables/imports, but I personally agree with you that this issue makes it much less enjoyable to code in Go which is why I made these changes to my compiler.
Use goimports. It's basically a fork of gofmt, written by Brad Fitzpatrick and now included in the go tools packages. You can configure your editor to run it whenever you save a file. You'll never have to worry about this problem again.
Use if false { ... } to comment out some code. The code inside the braces must be syntactically correct, but can be nonsense code otherwise.
If you are using the fmt package for general printing to console while you develop and test then you may find a better solution in the log package.
A lot of people have already commented with valid justification and I also acknowledge the original author's intention. However, Rob Pike mentioned in different forums that Go is the outcome of simplification of the processes that a few other mainstream programming languages either lack or not easy to achieve. It's Go's language semantics as well as to make the compilation faster, there are a lot of things that are adopted which initially seems inefficient.
To make it short, unused imports are considered as errors in Go as it blots the program and slows down the compilation. Using import for side effect (_) is a workaround, however, I find this confusing at times when there is a mix of valid imports with side effects along with side effects imported purely for the purpose of debugging/testing especially when the code base is large and there is a chance to forget and not delete unintentionally which may confuse other engineers/reviewers later. I used to comment out the unused ones, however, popular IDEs such as VS code and Goland can use goimports easily which does the insertion and deletion of the imports pretty well. Please refer to the link for more info, https://golang.org/doc/effective_go.html#blank_import
put this on top of your document and forget about unused imports:
import (
"bufio"
"fmt"
"os"
"path/filepath"
)
var _, _, _, _ = fmt.Println, bufio.NewReader, os.Open, filepath.IsAbs

How to write gnatcheck rules

Is it possible to write your own gnatcheck rules, and if so, can someone point me to a good reference? I am searching for a particular "style" that is being used, and would love if I could simply write a rule that says if you see said style, it will throw up a warning, or an error, this way we can flag when this isn't following a particular standard.
A bit of background may be helpful here. While the style checks hold out a lot of promise for enforcing user style guidelines, that isn't exactly what they are for.
The main purpose of those checks is to enforce Ada Core's (The folks who maintain the compiler) style on the sources of the Ada compiler itself. You may notice that the checks get automatically turned on if you try compiling one of the compiler's own source files.
It doesn't really serve AdaCore's purposes at all if the styles enforced by the checks themselves are user-configurable, so they added no feature like that.
Your first option if you want to use it yourself is to just stick to AdaCore's coding style. I haven't found it horrible in the past, so you may just look at doing that.
Still, making some kind of configurability would be a really cool feature for somebody to add. If you go this route, you probably would have to make it configurable (with the current behavior as the default), rather than just changing the checks. The reason is that you'd have to modify the compiler sources to accomplish this, and as I mentioned above, the compiler turns the checks on when compiling itself. You really don't want to have to reformat a ton of working Gnat compiler source files.
I'd really like to see someone do this at some point, as it would make the checks much more useful to those of us who work for someone besides AdaCore.
In addition to trashgod's reference, I think Section 7.1 of this PDF might be of some help:
http://extranet.eu.adacore.com/articles/HighIntegrityAda.pdf
For reference, the existing GNAT style checking is described in the GNAT User's Guide under ยง3.2.5 Style Checking. As the rules are enforced by the compiler, additional rules would require corresponding modifications.

GCC hidden/little-known features

This is my attempt to start a collection of GCC special features which usually do not encounter. this comes after #jlebedev in the another question mentioned "Effective C++" option for g++,
-Weffc++
This option warns about C++ code which breaks some of the programming guidelines given in the books "Effective C++" and "More Effective C++" by Scott Meyers. For example, a warning will be given if a class which uses dynamically allocated memory does not define a copy constructor and an assignment operator. Note that the standard library header files do not follow these guidelines, so you may wish to use this option as an occasional test for possible problems in your own code rather than compiling with it all the time.
What other cool features are there?
From time to time I go through the current GCC/G++ command line parameter documentation and update my compiler script to be even more paranoid about any kind of coding error. Here it is if you are interested.
Unfortunately I didn't document them so I forgot most, but -pedantic, -Wall, -Wextra, -Weffc++, -Wshadow, -Wnon-virtual-dtor, -Wold-style-cast, -Woverloaded-virtual, and a few others are always useful, warning me of potentially dangerous situations. I like this aspect of customizability, it forces me to write clean, correct code. It served me well.
However they are not without headaches, especially -Weffc++. Just a few examples:
It requires me to provide a custom copy constructor and assignment operator if there are pointer members in my class, which are useless since I use garbage collection. So I need to declare empty private versions of them.
My NonInstantiable class (which prevents instantiation of any subclass) had to implement a dummy private friend class so G++ didn't whine about "only private constructors and no friends"
My Final<T> class (which prevents subclassing of T if T derived from it virtually) had to wrap T in a private wrapper class to declare it as friend, since the standard flat out forbids befriending a template parameter.
G++ recognizes functions that never return a return value, and throw an exception instead, and whines about them not being declared with the noreturn attribute. Hiding behind always true instructions didn't work, G++ was too clever and recognized them. Took me a while to come up with declaring a variable volatile and comparing it against its value to be able to throw that exception unmolested.
Floating point comparison warnings. Oh god. I have to work around them by writing x <= y and x >= y instead of x == y where it is acceptable.
Shadowing virtuals. Okay, this is clearly useful to prevent stupid shadowing/overloading problems in subclasses but still annoying.
No previous declaration for functions. Kinda lost its importance as soon as I started copypasting the function declaration right above it.
It might sound a bit masochist, but as a whole, these are very cool features that increased my understanding of C++ and general programming.
What other cool features G++ has? Well, it's free, open, it's one of the most widely used and modern compilers, consistently outperforms its competitors, can eat almost anything people throw at it, available on virtually every platform, customizable to hell, continuously improved, has a wide community - what's not to like?
A function that returns a value (for example an int) will return a random value if a code path is followed that ends the function without a 'return value' statement. Not paying attention to this can result in exceptions and out of range memory writes or reads.
For example if a function is used to obtain the index into an array, and the faulty code path is used (the one that doesn't end with a return 'value' statement) then a random value will be returned which might be too big as an index into the array, resulting in all sorts of headaches as you wrongly mess up the stack or heap.

Visual studio 2005: is there a compiler option to initialize all stack-based variables to zero?

This question HAS had to be asked before, so it kills me to ask it again, but I can't find it for all of my google and searching stackoverflow.
I'm porting a bunch of linux code to windows, and a good chunk of it makes the assumption that everything is automatically initialized to zero or null.
int whatever;
char* something;
...and then immediately doing something that may leave 'something' null, and testing against 'something'
if(something == NULL)
{
.......
}
I would REALLY like not to have to go back throughout this code and say:
int whatever = 0;
char* something = NULL;
Even though that is the proper way to deal with it. It's just very time consuming.
Otherwise, I declare a variable, and it's initialized to something crazy if I don't set it myself.
This option doesn't exist in MSVC, and honestly, whoever coded your application made a big mistake. That code is not portable, as C/C++ say that uninitialized variables have an undefined value. I suggest setting the "treat warnings as errors" option and recompiling; MSVC should give you a warning every time a variable is used without being initialized.
No - there's no option to do that in MSVC.
Debug builds will initialize them with something else (0xcc I think), but not zero. Unfortunately, your code is bugged and needs fixed (of course this applies only to automatic variables -for statics and globals it's fine to assume they're zero initialized). I'm surprised there was any compiler that supported that behavior - if there's an option to do that in GCC, I haven't heard of it (but I'm no expert in the dusty corners of GCC).
You may hear that an earlier version of MSVC would init variables to zero in debug builds (similar to the way 0xcc is used in VS 2005), but as far as I know that's untrue.
edit ----------
Well, I'll be damned - GCC does (or did?) have the -finit-local-zero option. Looks like it's there mostly for Fortran support, I think.
I'd suggest using compiler warnings about using uninitialized variables to help you catch 99% of your problems. I know it's not a great bit of work, but it should be done if at all possible.
Interestingly, MSVC now does have the ability to do this. The Microsoft Security team wrote a blog post about it here, and there's a CppCon talk here.
Unfortunately, it doesn't seem like this option is exposed to the public. This page lists a bunch of 'hidden MSVC flags', and it includes an option called -initall, so that might be it.
What I ended-up doing was switching to /w4. At this level, it caught most of the "yeah, that's going to be an issue" areas of initialization. Otherwise, there's nothing that can change everything from being 0xcccccccc on initialization to 0x00000000 that I saw.
Massive thanks to everyone for answering this, and yes, we will tighten it up in the future.

Resources