From: Rob Pike
It is important to understand, however, that Go's runtime does not
include a virtual machine, such as is provided by the Java runtime.
-Go programs are compiled ahead of time to native machine code.
+Go programs are compiled ahead of time to native machine code
+(or JavaScript or WebAssembly, for some variant implementations).
Thus, although the term is often used to describe the virtual
environment in which a program runs, in Go the word “runtime”
is just the name given to the library providing critical language services.
@@ -296,28 +297,47 @@ is just the name given to the library providing critical language services.
What's up with Unicode identifiers?
-It was important to us to extend the space of identifiers from the
-confines of ASCII. Go's rule—identifier characters must be
+When designing Go, we wanted to make sure that it was not
+overly ASCII-centric,
+which meant extending the space of identifiers from the
+confines of 7-bit ASCII.
+Go's rule—identifier characters must be
letters or digits as defined by Unicode—is simple to understand
-and to implement but has restrictions. Combining characters are
-excluded by design, for instance.
-Until there
-is an agreed external definition of what an identifier might be,
-plus a definition of canonicalization of identifiers that guarantees
-no ambiguity, it seemed better to keep combining characters out of
-the mix. Thus we have a simple rule that can be expanded later
-without breaking programs, one that avoids bugs that would surely arise
-from a rule that admits ambiguous identifiers.
+and to implement but has restrictions.
+Combining characters are
+excluded by design, for instance,
+and that excludes some languages such as Devanagari.
-On a related note, since an exported identifier must begin with an
-upper-case letter, identifiers created from “letters”
-in some languages can, by definition, not be exported. For now the
+This rule has one other unfortunate consequence.
+Since an exported identifier must begin with an
+upper-case letter, identifiers created from characters
+in some languages can, by definition, not be exported.
+For now the
only solution is to use something like
+Since the earliest version of the language, there has been considerable
+thought into how best to expand the identifier space to accommodate
+programmers using other native languages.
+Exactly what to do remains an active topic of discussion, and a future
+version of the language may be more liberal in its definition
+of an identifier.
+For instance, it might adopt some of the ideas from the Unicode
+organization's recommendations
+for identifiers.
+Whatever happens, it must be done compatibly while preserving
+(or perhaps expanding) the way letter case determines visibility of
+identifiers, which remains one of our favorite features of Go.
+
+For the time being, we have a simple rule that can be expanded later
+without breaking programs, one that avoids bugs that would surely arise
+from a rule that admits ambiguous identifiers.
libc
, the C library.
Xæ¥æ¬èª
, which
-is clearly unsatisfactory; we are considering other options. The
-case-for-visibility rule is unlikely to change however; it's one
-of our favorite features of Go.
+is clearly unsatisfactory.
+Why does Go not have feature X?
@@ -345,6 +365,23 @@ Generics may well be added at some point. We don't feel an urgency for
them, although we understand some programmers do.
+Go was intended as a language for writing server programs that would be +easy to maintain over time. +(See this +article for more background.) +The design concentrated on things like scalability, readability, and +concurrency. +Polymorphic programming did not seem essential to the language's +goals at the time, and so was left out for simplicity. +
+ ++The language is more mature now, and there is scope to consider +some form of generic programming. +However, there remain some caveats. +
+Generics are convenient but they come at a cost in complexity in the type system and run-time. We haven't yet found a @@ -391,6 +428,9 @@ when used well, can result in clean error-handling code.
See the Defer, Panic, and Recover article for details. +Also, the Errors are values blog post +describes one approach to handling errors cleanly in Go by demonstrating that, +since errors are just values, the full power of Go can deployed in error handling.
-Concurrency and multi-threaded programming have a reputation -for difficulty. We believe this is due partly to complex -designs such as pthreads and partly to overemphasis on low-level details +Concurrency and multi-threaded programming have over time +developed a reputation for difficulty. We believe this is due partly to complex +designs such as +pthreads +and partly to overemphasis on low-level details such as mutexes, condition variables, and memory barriers. Higher-level interfaces enable much simpler code, even if there are still mutexes and such under the covers. @@ -488,6 +530,12 @@ by assigning to elements or doing deletions, it is safe for them to access the map concurrently without synchronization.
++As an aid to correct map use, some implementations of the language +contain a special check that automatically reports at run time when a map is modified +unsafely by concurrent execution. +
+Although Go is an open source project, the language and libraries are protected by a compatibility promise that prevents -changes that break existing programs. +changes that break existing programs, at least at the source code level +(programs may need to be recompiled occasionally to stay current). If your proposal violates the Go 1 specification we cannot even entertain the idea, regardless of its merit. -A future major release of Go may be incompatible with Go 1, but we're not ready -to start talking about what that might be. +A future major release of Go may be incompatible with Go 1, but discussions +on that topic have only just begun and one thing is certain: +there will be very few such incompatibilities introduced in the process. +Moreover, the compatibility promise encourages us to provide an automatic path +forward for old programs to adapt should that situation arise.
@@ -619,7 +671,8 @@ Why doesn't Go have "implements" declarations?
A Go type satisfies an interface by implementing the methods of that interface, nothing more. This property allows interfaces to be defined and used without -having to modify existing code. It enables a kind of structural typing that +needing to modify existing code. It enables a kind of +structural typing that promotes separation of concerns and improves code re-use, and makes it easier to build on patterns that emerge as the code develops. The semantics of interfaces is one of the main reasons for Go's nimble, @@ -764,7 +817,9 @@ examples and also have them be statically checked. Can I convert a []T to an []interface{}?
-Not directly, because they do not have the same representation in memory.
+Not directly.
+It is disallowed by the language specification because the two types
+do not have the same representation in memory.
It is necessary to copy the elements individually to the destination
slice. This example converts a slice of int
to a slice of
interface{}
:
@@ -806,22 +861,30 @@ Why is my nil error value not equal to nil?
-Under the covers, interfaces are implemented as two elements, a type and a value.
-The value, called the interface's dynamic value,
-is an arbitrary concrete value and the type is that of the value.
-For the int
value 3, an interface value contains,
-schematically, (int
, 3
).
+Under the covers, interfaces are implemented as two elements, a type T
+and a value V
.
+V
is a concrete value such as an int
,
+struct
or pointer, never an interface itself, and has
+type T
.
+For instance, if we store the int
value 3 in an interface,
+the resulting interface value has, schematically,
+(T=int
, V=3
).
+The value V
is also known as the interface's
+dynamic value,
+since a given interface variable might hold different values V
+(and corresponding types T
)
+during the execution of the program.
-An interface value is nil
only if the inner value and type are both unset,
-(nil
, nil
).
+An interface value is nil
only if the V
and T
+are both unset, (T=nil
, V
is not set),
In particular, a nil
interface will always hold a nil
type.
If we store a nil
pointer of type *int
inside
an interface value, the inner type will be *int
regardless of the value of the pointer:
-(*int
, nil
).
+(T=*int
, V=nil
).
Such an interface value will therefore be non-nil
-even when the pointer inside is nil
.
+even when the pointer value V
inside is nil
.
@@ -842,7 +905,7 @@ func returnsError() error {
If all goes well, the function returns a nil
p
,
so the return value is an error
interface
-value holding (*MyError
, nil
).
+value holding (T=*MyError
, V=nil
).
This means that if the caller compares the returned error to nil
,
it will always look as if there was an error even if nothing bad happened.
To return a proper nil
error
to the caller,