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!
Related
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
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.
I cam across some code today that suprised me with a 'print' that wasn't defined. After a little playing I determined that you can just use a print to get things dumped to the console
e.g.
print("Hello World")
So it seems to be some sort of builtin but I can't find any reference to it (and I thought the go rules were lowercase functions never imported anyway)
Is this well known and if so are there other convenience functions or am I just very, very confused?
One other point -- this print doesn't use the magic formatting tricks (%v) of fmt.Printf -- If you print maps or structs you seem to get their address.
print and println are defined here.
Their purpose is explained here.
You are right, and someone else has already complained about it. It's been added to the built-in documentation for the next Go release (go1.2).
Package builtin
func print
func print(args ...Type)
The print built-in function formats its arguments in an
implementation-specific way and writes the result to standard error.
Print is useful for bootstrapping and debugging; it is not guaranteed
to stay in the language.
func println
func println(args ...Type)
The println built-in function formats its arguments in an
implementation-specific way and writes the result to standard error.
Spaces are always added between arguments and a newline is appended.
Println is useful for bootstrapping and debugging; it is not
guaranteed to stay in the language.
For the work I'm doing to integrate with an existing library, I ended up needing to write some additional C code to provide an interface that was usable through CGo.
In order to avoid redundant data copies, I would like to be able to pass some standard Go types (e.g. Go strings) to these C adapter functions.
I can see that there are GoString and GoInterface types defined in the header CGo generates for use by exported Go functions, but is there any way to use these types in my own function prototypes that CGo will recognise?
At the moment, I've ended up using void * in the C prototypes and passing unsafe.Pointer(&value) on the Go side. This is less clean than I'd like though (for one thing, it gives the C code the ability to write to the value).
Update:
Just to be clear, I do know the difference between Go's native string type and C char *. My point is that since I will be copying the string data passed into my C function anyway, it doesn't make sense to have the code on the Go side make its own copy.
I also understand that the string layout could change in a future version of Go, and its size may differ by platform. But CGo is already exposing type definitions that match the current platform to me via the documented _cgo_export.h header it generates for me, so it seems a bit odd to talk of it being unspecified:
typedef struct { char *p; int n; } GoString;
But there doesn't seem to be a way to use this definition in prototypes visible to CGo. I'm not overly worried about binary compatibility, since the code making use of this definition would be part of my Go package, so source level compatibility would be enough (and it wouldn't be that big a deal to update the package if that wasn't the case).
Not really. You cannot safely mix, for example Go strings (string) and C "strings" (*char) code without using the provided helpers for that, ie. GoString and CString. The reason is that to conform to the language specs a full copy of the string's content between the Go and C worlds must be made. Not only that, the garbage collector must know what to consider (Go strings) and what to ignore (C strings). And there are even more things to do about this, but let me keep it simple here.
Similar and/or other restrictions/problems apply to other Go "magical" types, like map or interface{} types. In the interface types case (but not only it), it's important to realize that the inner implementation of an interface{} (again not only this type), is not specified and is implementation specific.
That's not only about the possible differences between, say gc and gccgo. It also means that your code will break at any time the compiler developers decide to change some detail of the (unspecified and thus non guaranteed) implementation.
Additionally, even though Go doesn't (now) use a compacting garbage collector, it may change and without some pinning mechanism, any code accessing Go run time stuff directly will be again doomed.
Conclusion: Pass only simple entities as arguments to C functions. POD structs with simple fields are safe as well (pointer fields generally not). From the complex Go types, use the provided helpers for Go strings, they exists for a (very good) reason.
Passing a Go string to C is harder than it should be. There is no really good way to do it today. See https://golang.org/issue/6907.
The best approach I know of today is
// typedef struct { const char *p; ptrdiff_t n; } gostring;
// extern CFunc(gostring s);
import "C"
func GoFunc(s string) {
C.CFunc(*(*C.gostring)(unsafe.Pointer(&s)))
}
This of course assumes that Go representation of a string value will not change, which is not guaranteed.
In all the projects I've worked with in other languages the bracing-style of choice has been the Allman Style(aka ANSI style). The lack of a free-form bracing style(parenthesis too) is something I miss from other C-style syntax family of languages when working in Go.
Can anyone come up with a way to make the Go compiler accept the following bracing-style?
package main
import "fmt"
func main()
{
f()
fmt.Println("Returned normally from f.")
}
func f()
{
fmt.Println("In function f.")
}
Note I am aware of the arguments for why Go was designed with such artificial 'limitation', but I'm not really buying into it. I'm a firm believer that the bracing-style used should really be decided by the coding-standard adopted by the people or company working on the code-base rather than being forced upon by the language itself.
As such please consider my question within the scope of 'how it can be done' rather than 'why not to do it and just adapt'.
Thanks
I double the braces up.
if x < 0 {
{
return sqrt(-x) + "i"
}}
It's not ideal but better than trying to scan columns 1-120 for matching braces.
This may not be exactly what you are looking for, but it is one possible way.
You could write a 'translator program,' essentially an incredibly simple compiler that converts from what you wrote, effectively a Go variant, to what the Go compiler itself expects.
You could do that with something along the lines of a program, even shell script, that applies the regular expression 's/(\n)$^\s*{/{\1/g' to the entire program (though it would need to look at the full string of the file and not break it up line-by-line, so you couldn't just pass that expression as an argument to sed, for example). Then write the converted file out to a temporary one, and run the Go compiler on it.
This method has the advantage of not requiring any changes to Go itself, though the disadvantage is that your files will not compile without your extra script. If you normally use a Makefile, this is probably fine, but sometimes could still be inconvenient.
Succinctly, no. The language is (or was a year or more ago) defined with semi-colons, and the compiler inserts semi-colons implicitly at the ends of lines - unless there's a brace at the end of the line. So, if you write a condition (which doesn't need the parentheses, please note) and do not put an open brace at the end of the line, then the Go compiler inserts one for you - leaving a null statement after the if, and the braces enclosing a block that is executed unconditionally.
#epw suggests a reformatter; I think that is a reasonable suggestion. Go comes with gofmt to convert to the canonical Go style. You'd have to write something to convert from canonical to Allman style, and vice versa, and ensure that you pre-compile your Go-Allman source into Go-canonical format before compiling it to object files. On the whole, this is more traumatic than accepting that Go has its own rules which are no more eccentric than Python's rules and that it is simplest to go with the flow and accept that coding in Go involves coding in non-Allman (approximately K&R) style. (I like and use Allman style in C; I use Go-style in Go.)
Give a try to https://gofork.org
forkgo supports allman/horstmann style:
package main
import
( "fmt"
)
func main()
{ if false
{ fmt.Println("jack")
fmt.Println("forkgo")
} else
{ fmt/
.Println("hello")
fmt.Println("forkgo")
}
}