By analogy with this question about tags I note that there are several uses of comments in go beyond pure commentary.
Examples:
go:generate can be used for code generation.
godoc uses the function name to indicate comments it should interpret
build constraints
Are there any others I've missed?
Is there a definitive list somewhere?
Some third party packages like gocontracts and go-swagger use them as well. How can they avoid conflicting with each other?
As noted comments are directives in go not just comments.
There is at the time of writing no definitive list.
This as logged as an golang issue 28532.
Therefore I propose using this answer to make one.
Uses in the go core language and tools themselves:
go:generate can be used for code generation.
godoc uses the function name to indicate comments it should interpret
Examples - document the expected output of a test (thanks #Butuzov)
build constraints (starting with '// +build')
Import comments e.g. 'package math // import "path"'
Notable uses in third party packages
gocontracts - specify preconditions as comments
go-swagger - document a ReST API using swagger
golangci e.g. //nolint[:linter1,linter2,...]
How can they avoid conflicting with each other?
If you are developing a tool that really needs to treat comments as attributes and wish to avoid conflict with other similar uses prefix your comments with a namespace like "{mytool}: "
There are some conscious attempts at namespacing.
Magic comments built into go use the "go: " prefix as in "go:generate"
(except where they don't)
go-swagger uses "swagger: "
However you still need to approach this with caution and check the list here or any other source you can find.
Also consider whether comments are the best or only approach rather than using functions instead.
Compare for instance (gocontracts):
// SomeFunc ensures:
// * !strings.HasSuffix(result, "smth")
func SomeFunc(x int) (result string) {
// ...
}
with (godbc)
func SomeFunc(x int) (result string) {
godbc.Require(strings.HasSuffix(result,"smth");
}
Examples - Allow to test function for example output.
Copy/Paste from link above.
package stringutil_test
import (
"fmt"
"github.com/golang/example/stringutil"
)
func ExampleReverse() {
fmt.Println(stringutil.Reverse("hello"))
// Output: olleh
}
Related
How to create visible Go documentation?
That is easy to create documentation for any function in go like that:
package main
// documentation example
func DocumentedFunction() bool {
return true
}
And i can see that documentation when i call that function:
Can i write package documentation, that will be visible from editor/IDE? Do i have to install additional tools to achieve similar behaviour for package documentation?
According to the official Go documentation and this link, it should be possible to create documentation for an entire package the same way you would do it for a function:
To document a function, type, constant, variable, or even a complete package, write a regular comment directly preceding its declaration, with no blank line in between.
For example: the strings package:
// Package strings implements simple functions to manipulate UTF-8 encoded strings.
//
// For information about UTF-8 strings in Go, see https://blog.golang.org/strings.
package strings
..
..
rest of the file
So you basically just add a normal comment above the package keyword.
I'm maintaining some code written using Go (golang), Viper and Cobra.
On one line, it has:
rootCmd.PersistentFlags().String("cfg", "", "A description")
And then on the following line it has
rootCmd.PersistentFlags().StringP("output", "o", ".", "Another description")
What is the difference between String and StringP in this context?
Looking at example usages in various tutorials, there seem to be P and non-P versions of various methods, such as StringVarP and StringVar.
What is the difference between these versions? What is the significance of the P?
Is there a way I can tell whether a given method has a P or non-P counterpart?
Search engines tend to take me to cobra or viper tutorial pages, which make use of these methods without explaining the P or non-P counterpart.
I found some material on pflags which suggested it might be to do with whether the parameter has a short (one-letter) form. Could this be it?
Post-edit note: Having received answers to this question, it seems spf13/pflag is indeed used under the hood by the above mentioned golang frameworks. However, it's not immediately clear that one should go looking through the pflags documentation when using cobra or viper.
As this is a Q&A site, I've reverted an edit that removed many of the keywords I would have entered when looking for this answer, as I feel others looking for the same information will be better served that way.
The P suffix denotes a function that accepts a single letter flag name in addition to the full name, as documented in the usage section of the pflag docs:
The pflag package also defines some new functions that are not in
flag, that give one-letter shorthands for flags. You can use these by
appending 'P' to the name of any function that defines a flag.
To answer your individual questions:
what's the difference: the P functions take an extra parameter: the single letter name. This short flag can be used with a single -.
which methods have a P counterpart: all of them, as can be seen in the pflag reference
As for why this is documented in pflag and not viper or cobra, this is because both viper and cobra use the pflag library.
How to get annotation of go language function?
Example:
// #annotation1
// #annotation2
func Tags() string {
return ""
}
How to get the "#annotation1" and "#annotation2"?
Short answer, there is no native support for annotations in Golang. What's being used if tags, which you can get from the reflect package.
So, you do not have annotations in Go, and to my knowledge there is no library which provides them. Depending of what you want to do, usually tags are more than enough, and you can use the language's power to achieve the desired results.
It should be possible to implement them as you can get the documentation strings, just like PHP does. However, in the big majority of cases it won't be necessary.
EDIT:
In Go, you have access to the documentation of structs, fields, methods, interfaces, functions (godoc isn't magical) through the ast package. However, it requires parsing the files, there is no function such as type.getDocComments() as in PHP.
So, an implementation is theoretically possible. However, the kind of annotations you're asking for are simply not part of Golang's philosophy. There are plenty of libraries that extensively use tags, but none use annotations.
I do not know of any native support for something that pulls specific tags from comments - however, the builtin functionality of godoc does pull from the comments directly adjacent to functions. If you are trying to build documentation, this may be useful.
In addition to godoc, I know that the golang plugin for IntelliJ pulls these comments as the help/documentation for inline completions and suggestions.
Hope this helps!
I would like to define my Error Codes in a package models.
error.go
package models
const{
EOK = iota
EFAILED
}
How can I use them in another package without referring to them as models.EOK. I would like to use directly as EOK, since these codes would be common across all packages.
Is it the right way to do it? Any better alternatives?
To answer you core question
You can use the dot import syntax to import the exported symbols from another package directly into your package's namespace (godoc):
import . "models"
This way you could directly refer to the EOK constant without prefixing it with models.
However I'd strongly advice against doing so, as it generates rather unreadable code. see below
General/style advice
Don't use unprefixed export path like models. This is considered bad style as it will easily globber. Even for small projects, that are used only internally, use something like myname/models. see goblog
Regarding your question about error generation, there are functions for generating error values, e.g. errors.New (godoc) and fmt.Errorf (godoc).
For a general introduction on go and error handling see goblog
W.r.t. the initial question, use a compact package name, for example err.
Choosing an approach to propagating errors, and generating error messages depends on the scale and complexity of the application. The error style you show, using an int, and then a function to decode it, is quite C-ish.
That style was partly caused by:
the lack of multiple value returns (unlike Go),
the need to use a simple type (to be easily propagated), and
that gets translated to text with a function (unlike Go's error interface), so that the local language strings can be changed.
For small apps with simple errors strings. I put the packages' error strings at the head of a package file, and just return them, maybe using errors.New(...), or fmt.Errorf if the string needs to be completed using some data.
That 'int' style of error reporting doesn't offer something as flexible as Go's error interface. The error interface lets us build information-rich error structures, to return useful information, and not just an int value or string.
An implication is different packages can yield different real-types which implement the Error interface. We don't need to agree a single error real-type across an entire set of packages. So error is an interface which can be easily propagated, like an int, yet, the real-type of error can be much richer than an int. Error generation (implementing Error) can be as centralised or distributed as we need, unlike strerror()-style functions which can be awkward to extend.
I am currently writing ExampleFuncs in my Go test scripts. For example:
package hello
import "testing"
func ExampleGetSymbol() {
data := GetSymbol("AAPL")
fmt.Println(len(data.Data))
// Output: 21
}
Now, this gives me two benefits:
This example is executed when I am running go test and
It appears in the godoc documentation under func GetSymbol
One thing bothers me and I am wondering if there is anything I should do about it.
For the user that's trying to learn from this example, the line
data := GetSymbol("AAPL")
should actually be
data := hello.GetSymbol("AAPL")
but since the test is in the same scope as the package, I cannot use it like this.
So I guess the distilled version of my question would be:
Is there a way to allow package.field notation inside the package scope?
Thanks in advance
Rather than putting this in package hello, put it in package hello_test. You're allowed to have both hello and hello_test packages in the same directory, and it allows (requires) you to create your examples the way you're suggesting.
Incidentally, this also causes you to write your test cases (at least for this file) only to the public API. This is often a good thing. But if you need to write to private functions, you can split your tests into separate files, some in the hello package and some in hello_test.
BTW, documentation for this is slightly buried. You can find it in the "Test packages" section of the go cmd documentation.