aboutsummaryrefslogtreecommitdiff
path: root/content/constants.article
diff options
context:
space:
mode:
Diffstat (limited to 'content/constants.article')
-rw-r--r--content/constants.article53
1 files changed, 27 insertions, 26 deletions
diff --git a/content/constants.article b/content/constants.article
index 5148cf1..c165733 100644
--- a/content/constants.article
+++ b/content/constants.article
@@ -1,10 +1,11 @@
-Constants
+# Constants
25 Aug 2014
Tags: constants
+Summary: Go is a statically typed language that does not permit operations that mix numeric types. You can't add a `float64` to an `int`, or even an `int32` to an `int`. Yet it is legal to write `1e6*time.Second` or `math.Exp(1)` or even `1<<('\t'+2.0)`. In Go, constants, unlike variables, behave pretty much like regular numbers. This post explains why that is and what it means.
Rob Pike
-* Introduction
+## Introduction
Go is a statically typed language that does not permit operations that mix numeric types.
You can't add a `float64` to an `int`, or even an `int32` to an `int`.
@@ -12,7 +13,7 @@ Yet it is legal to write `1e6*time.Second` or `math.Exp(1)` or even `1<<('\t'+2.
In Go, constants, unlike variables, behave pretty much like regular numbers.
This post explains why that is and what it means.
-* Background: C
+## Background: C
In the early days of thinking about Go, we talked about a number of problems
caused by the way C and its descendants let you mix and match numeric types.
@@ -24,7 +25,7 @@ Although to a seasoned C programmer the result of a calculation like
long signed int i = -1;
... i + u ...
-may be familiar, it isn't _a_priori_ obvious.
+may be familiar, it isn't _a priori_ obvious.
How big is the result?
What is its value?
Is it signed or unsigned?
@@ -67,7 +68,7 @@ able to write things like `math.Sqrt(2)` without being chided by the compiler.
In short, constants in Go just work, most of the time anyway.
Let's see how that happens.
-* Terminology
+## Terminology
First, a quick definition.
In Go, `const` is a keyword introducing a name for a scalar value such as `2` or `3.14159` or `"scrumptious"`.
@@ -82,7 +83,7 @@ more intricate properties of more intricate values.
But in Go, a constant is just a simple, unchanging value, and from here on we're talking only about Go.
-* String constants
+## String constants
There are many kinds of numeric constants—integers,
floats, runes, signed, unsigned, imaginary,
@@ -91,19 +92,19 @@ String constants are easy to understand and provide a smaller space in which
to explore the type issues of constants in Go.
A string constant encloses some text between double quotes.
-(Go also has raw string literals, enclosed by backquotes ``````,
+(Go also has raw string literals, enclosed by backquotes ````````,
but for the purpose of this discussion they have all the same properties.)
Here is a string constant:
"Hello, 世界"
(For much more detail about the representation and interpretation of strings,
-see [[https://blog.golang.org/strings][this blog post]].)
+see [this blog post](https://blog.golang.org/strings).)
What type does this string constant have?
The obvious answer is `string`, but that is _wrong_.
-This is an _untyped_string_constant_, which is to say it is a constant textual
+This is an _untyped string constant_, which is to say it is a constant textual
value that does not yet have a fixed type.
Yes, it's a string, but it's not a Go value of type `string`.
It remains an untyped string constant even when given a name:
@@ -152,14 +153,14 @@ or
m = hello
because, unlike the typed constants `typedHello` and `myStringHello`,
-the untyped constants `"Hello,`世界"` and `hello` _have_no_type_.
+the untyped constants `"Hello, 世界"` and `hello` _have no type_.
Assigning them to a variable of any type compatible with strings works without error.
These untyped string constants are strings,
of course, so they can only be used where a string is allowed,
but they do not have _type_ `string`.
-* Default type
+## Default type
As a Go programmer, you have certainly seen many declarations like
@@ -214,18 +215,18 @@ If the constant has a type, that goes into the interface, as this example shows:
.play -edit constants/default3.go /START/,/STOP/
(For more information about how interface values work,
-see the first sections of [[https://blog.golang.org/laws-of-reflection][this blog post]].)
+see the first sections of [this blog post](https://blog.golang.org/laws-of-reflection).)
In summary, a typed constant obeys all the rules of typed values in Go.
On the other hand, an untyped constant does not carry a Go type in the same
way and can be mixed and matched more freely.
It does, however, have a default type that is exposed when, and only when, no other type information is available.
-* Default type determined by syntax
+## Default type determined by syntax
The default type of an untyped constant is determined by its syntax.
For string constants, the only possible implicit type is `string`.
-For [[https://golang.org/ref/spec#Numeric_types][numeric constants]], the implicit type has more variety.
+For [numeric constants](https://golang.org/ref/spec#Numeric_types), the implicit type has more variety.
Integer constants default to `int`, floating-point constants `float64`,
rune constants to `rune` (an alias for `int32`),
and imaginary constants to `complex128`.
@@ -235,7 +236,7 @@ Here's our canonical print statement used repeatedly to show the default types i
(Exercise: Explain the result for `'x'`.)
-* Booleans
+## Booleans
Everything we said about untyped string constants can be said for untyped boolean constants.
The values `true` and `false` are untyped boolean constants that can be assigned to any boolean variable,
@@ -246,7 +247,7 @@ but once given a type, boolean variables cannot be mixed:
Run the example and see what happens, then comment out the "Bad" line and run it again.
The pattern here follows exactly that of string constants.
-* Floats
+## Floats
Floating-point constants are just like boolean constants in most respects.
Our standard example works as expected in translation:
@@ -283,7 +284,7 @@ prints `10`, as one would expect.
In a related way, floating-point constants may have very high precision,
so that arithmetic involving them is more accurate.
-The constants defined in the [[https://golang.org/pkg/math][math]] package are given with many more digits than are
+The constants defined in the [math](https://golang.org/pkg/math) package are given with many more digits than are
available in a `float64`. Here is the definition of `math.Pi`:
Pi = 3.14159265358979323846264338327950288419716939937510582097494459
@@ -305,7 +306,7 @@ soft underflows, and `NaNs` arise in constant expressions.
(Division by a constant zero is a compile-time error,
and when everything is a number there's no such thing as "not a number".)
-* Complex numbers
+## Complex numbers
Complex constants behave a lot like floating-point constants.
Here's a version of our now-familiar litany translated into complex numbers:
@@ -342,10 +343,10 @@ The output is `2` `and` `2`.
Even though `Two` is a complex constant, it can be assigned to scalar floating-point variables.
This ability for a constant to "cross" types like this will prove useful.
-* Integers
+## Integers
At last we come to integers.
-They have more moving parts—[[https://golang.org/ref/spec#Numeric_types][many sizes, signed or unsigned, and more]]—but
+They have more moving parts—[many sizes, signed or unsigned, and more](https://golang.org/ref/spec#Numeric_types)—but
they play by the same rules.
For the last time, here is our familiar example, using just `int` this time:
@@ -397,7 +398,7 @@ This type-checking can catch mistakes like this one:
If the compiler complains about your use of a constant, it's likely a real bug like this.
-* An exercise: The largest unsigned int
+## An exercise: The largest unsigned int
Here is an informative little exercise.
How do we express a constant representing the largest value that fits in a `uint`?
@@ -409,7 +410,7 @@ but we want `uint`, not `uint32`.
The `int` and `uint` types have equal unspecified numbers of bits, either 32 or 64.
Since the number of bits available depends on the architecture, we can't just write down a single value.
-Fans of [[http://en.wikipedia.org/wiki/Two's_complement][two's-complement arithmetic]],
+Fans of [two's-complement arithmetic](http://en.wikipedia.org/wiki/Two's_complement),
which Go's integers are defined to use, know that the representation of `-1` has all its bits set to 1,
so the bit pattern of `-1` is internally the same as that of the
largest unsigned integer.
@@ -424,7 +425,7 @@ A conversion won't help either, for the same reason:
.play -edit constants/exercise2.go /const/
Even though at run-time a value of -1 can be converted to an unsigned integer, the rules
-for constant [[https://golang.org/ref/spec#Conversions][conversions]] forbid this kind of coercion at compile time.
+for constant [conversions](https://golang.org/ref/spec#Conversions) forbid this kind of coercion at compile time.
That is to say, this works:
.play -edit constants/exercise3.go /START/,/STOP/
@@ -456,13 +457,13 @@ Here, then, is our constant:
.play -edit constants/exercise6.go /START/,/STOP/
Whatever the number of bits it takes to represent a `uint` in the current execution environment
-(on the [[https://blog.golang.org/playground][playground]], it's 32),
+(on the [playground](https://blog.golang.org/playground), it's 32),
this constant correctly represents the largest value a variable of type `uint` can hold.
If you understand the analysis that got us to this result,
you understand all the important points about constants in Go.
-* Numbers
+## Numbers
The concept of untyped constants in Go means that all the numeric constants,
whether integer, floating-point, complex,
@@ -486,7 +487,7 @@ written as untyped constants they can be assigned to a variable of any integer t
.play -edit constants/numbers1.go /START/,/STOP/
-The output from this snippet is: `1`1`1`1`1`(1+0i)`1`.
+The output from this snippet is: `1 1 1 1 1 (1+0i) 1`.
You can even do nutty stuff like