false
and true
, which are two predeclared (built-in) named constants. Custom named constant declarations will be introduced below in this article.
nil
is the only untyped value which has no default type. We will learn more about nil
in other Go 101 articles later.
nil
and some boolean results returned by some operations which will be introduced in other articles later.
string
.
bool
.
int
.
rune
(a.k.a., int32
).
float64
.
complex128
.
T(v)
to convert a value v
to the type denoted by T
(or simply speaking, type T
). If the conversion T(v)
is legal, Go compilers view T(v)
as a typed value of type T
. Surely, for a certain type T
, to make the conversion T(v)
legal, the value v
can't be arbitrary.
v
, there are two scenarios where T(v)
is legal.
v
(or the literal denoted by v
) is representable as a value of a basic type T
. The result value is a typed constant of type T
.
v
is an integer type (int
or rune
) and T
is a string type. The result of T(v)
is a string of type T
and contains the UTF-8 representation of the integer as a Unicode code point. Integer values outside the range of valid Unicode code points result strings represented by "\uFFFD"
(a.k.a., "\xef\xbf\xbd"
). 0xFFFD
is the code point for the Unicode replacement character. The result string of a conversion from an integer always contains one and only one rune. (Note, later Go version might only allow converting rune or byte integers to strings. Since Go Toolchain 1.15, the go vet
command warns on conversions from non-rune and non-byte integers to strings.)
v
to be a constant. If v
is a constant, then the result of the conversion is also a constant; otherwise, the result is not a constant.
// Rounding happens in the following 3 lines.
complex128(1 + -1e-1000i) // 1.0+0.0i
float32(0.49999999) // 0.5
float32(17000000000000000)
// No rounding in the these lines.
float32(123)
uint(1.0)
int8(-123)
int16(6+0i)
complex128(789)
string(65) // "A"
string('A') // "A"
string('\u68ee') // "森"
string(-1) // "\uFFFD"
string(0xFFFD) // "\uFFFD"
string(0x2FFFFFFFF) // "\uFFFD"
// 1.23 is not representable as a value of int.
int(1.23)
// -1 is not representable as a value of uint8.
uint8(-1)
// 1+2i is not representable as a value of float64.
float64(1+2i)
// Constant -1e+1000 overflows float64.
float64(-1e1000)
// Constant 0x10000000000000000 overflows int.
int(0x10000000000000000)
// The default type of 65.0 is float64,
// which is not an integer type.
string(65.0)
// The default type of 66+0i is complex128,
// which is not an integer type.
string(66+0i)
-1e1000
and 0x10000000000000000
), may even not be able to represent as a value of its default type.
(T)(v)
to avoid ambiguities. Such situations often happen in case of T
is not an identifier.
const
is used to declare named constants. The following program contains some constant declarations.
package main
// Declare two individual constants. Yes,
// non-ASCII letters can be used in identifiers.
const π = 3.1416
const Pi = π // <=> const Pi = 3.1416
// Declare multiple constants in a group.
const (
No = !Yes
Yes = true
MaxDegrees = 360
Unit = "radian"
)
func main() {
// Declare multiple constants in one line.
const TwoPi, HalfPi, Unit2 = π * 2, π * 0.5, "degree"
}
=
symbol in the above constant declaration group as a constant specification.
*
symbol is the multiplication operator and the !
symbol is the boolean-not operator. Operators will be introduced in the next article, common operators.
=
symbol means "bind" instead of "assign". We should interpret each constant specification as a declared identifier is bound to a corresponding basic value literal. Please read the last section in the current article for more explanations.
π
and Pi
are both bound to the literal 3.1416
. The two named constants may be used at many places in code. Without constant declarations, the literal 3.1416
would be populated at those places. If we want to change the literal to 3.14
later, many places need to be modified. With the help of constant declarations, the literal 3.1416
will only appear in one constant declaration, so only one place needs to be modified. This is the main purpose of constant declarations.
No
and Yes
can be exchanged.
X
and Y
are both float32
and the types of A
and B
are both int64
.
const X float32 = 3.14
const (
A, B int64 = -3, 5
Y float32 = 2.718
)
A
and B
in the above example.
X
, Y
, A
and B
are all typed constants.
const X = float32(3.14)
const (
A, B = int64(-3), int64(5)
Y = float32(2.718)
)
// error: 256 overflows uint8
const a uint8 = 256
// error: 256 overflows uint8
const b = uint8(255) + uint8(1)
// error: 128 overflows int8
const c = int8(-128) / int8(-1)
// error: -1 overflows uint
const MaxUint_a = uint(^0)
// error: -1 overflows uint
const MaxUint_b uint = ^0
^
is bitwise-not operator.
uint
value has only 32 bits on 32-bit OSes. (1 << 64) - 1
is not representable as 32-bit values. (Here, <<
is bitwise-left-shift operator.)
const MaxUint uint = (1 << 64) - 1
uint
constant and bind the largest uint
value to it? Use the following way instead.
const MaxUint = ^uint(0)
int
constant and bind the largest int
value to it. (Here, >>
is bitwise-right-shift operator.)
const MaxInt = int(^uint(0) >> 1)
// NativeWordBits is 64 or 32.
const NativeWordBits = 32 << (^uint(0) >> 63)
const Is64bitOS = ^uint(0) >> 63 != 0
const Is32bitOS = ^uint(0) >> 32 == 0
!=
and ==
are not-equal-to and equal-to operators.
const (
X float32 = 3.14
Y // here must be one identifier
Z // here must be one identifier
A, B = "Go", "language"
C, _
// In the above line, the blank identifier
// is required to be present.
)
const (
X float32 = 3.14
Y float32 = 3.14
Z float32 = 3.14
A, B = "Go", "language"
C, _ = "Go", "language"
)
iota
in constant declarations
iota
constant generator feature brings much convenience to Go programming. iota
is a predeclared constant which can only be used in other constant declarations. It is declared as
const iota = 0
iota
in code may be not always 0
. When the predeclared iota
constant is used in a custom constant declaration, at compile time, within the custom constant declaration, its value will be reset to 0
at the first constant specification of each group of constants and will increase 1
constant specification by constant specification. In other words, in the nth constant specification of a constant declaration, the value of iota
is n (starting from zero). So iota
is only useful in group-style constant declarations.
iota
constant generator features. Please read the comments to get what will happen at compile time. The +
symbol in this example is the addition operator.
package main
func main() {
const (
k = 3 // now, iota == 0
m float32 = iota + .5 // m float32 = 1 + .5
n // n float32 = 2 + .5
p = 9 // now, iota == 3
q = iota * 2 // q = 4 * 2
_ // _ = 5 * 2
r // r = 6 * 2
s, t = iota, iota // s, t = 7, 7
u, v // u, v = 8, 8
_, w // _, w = 9, 9
)
const x = iota // x = 0
const (
y = iota // y = 0
z // z = 1
)
println(m) // +1.500000e+000
println(n) // +2.500000e+000
println(q, r) // 8 12
println(s, t, u, v, w) // 7 7 8 8 9
println(x, y, z) // 0 0 1
}
iota
constant generator feature. Surely, in practice, we should use it in more meaningful ways. For example,
const (
Failed = iota - 1 // == -1
Unknown // == 0
Succeeded // == 1
)
const (
Readable = 1 << iota // == 1
Writable // == 2
Executable // == 4
)
-
symbol is the subtraction operator, and the <<
symbol is the left-shift operator. Both of these operators will be introduced in the next article.
var
keyword, which is followed by the declared variable name. Variable names must be identifiers.
var lang, website string = "Go", "https://golang.org"
var compiled, dynamic bool = true, false
var announceYear int = 2009
// The types of the lang and dynamic variables
// will be deduced as built-in types "string"
// and "bool" by compilers, respectively.
var lang, dynamic = "Go", false
// The types of the compiled and announceYear
// variables will be deduced as built-in
// types "bool" and "int", respectively.
var compiled, announceYear = true, 2009
// The types of the website variable will be
// deduced as the built-in type "string".
var website = "https://golang.org"
// Both are initialized as blank strings.
var lang, website string
// Both are initialized as false.
var interpreted, dynamic bool
// n is initialized as 0.
var n int
()
. For example:
var (
lang, bornYear, compiled = "Go", 2007, true
announceAt, releaseAt int = 2009, 2012
createdBy, website string
)
go fmt
command provided in Go Toolchain. In the above example, each of the three lines are enclosed in ()
this is known as variable specification.
=
means assignment. Once a variable is declared, we can modify its value by using pure value assignments. Like variable declarations, multiple values can be assigned in a pure assignment.
=
symbol in a pure assignment are called destination or target values. They must be addressable values, map index expressions, or the blank identifier. Value addresses and maps will be introduced in later articles.
const N = 123
var x int
var y, z float32
N = 9 // error: constant N is not modifiable
y = N // ok: N is deduced as a float32 value
x = y // error: type mismatch
x = N // ok: N is deduced as an int value
y = x // error: type mismatch
z = y // ok
_ = y // ok
x, y = y, x // error: type mismatch
x, y = int(y), float32(x) // ok
z, y = y, z // ok
_, y = y, z // ok
z, _ = y, z // ok
_, _ = y, z // ok
x, y = 69, 1.23 // ok
var a, b int
a = b = 123 // syntax error
package main
func main() {
// Both lang and year are newly declared.
lang, year := "Go language", 2007
// Only createdBy is a new declared variable.
// The year variable has already been
// declared before, so here its value is just
// modified, or we can say it is redeclared.
year, createdBy := 2009, "Google Research"
// This is a pure assignment.
lang, year = "Go", 2012
print(lang, " is created by ", createdBy)
println(", and released at year", year)
}
var
keyword and variable types must be omitted.
:=
instead of =
.
:=
. But there must be at least one new variable at the left.
:=
sign must pure identifiers. This means some other items which can be assigned to, which will be introduced in other articles, can't appear at the left of :=
. These items include qualified identifiers, container elements, pointer dereferences and struct field selectors. Pure assignments have no such limit.
x
is assignable to y
if y = x
is a legal statement (compiles okay). Assume the type of y
is Ty
, sometimes, for description convenience, we can also say x
is assignable to type Ty
.
x
is assignable to y
, then y
should be mutable, and the types of x
and y
are identical or x
can be implicitly converted to the type of y
. Surely, y
can also be the blank identifier _
.
r
is only used as destination.
package main
// Some package-level variables.
var x, y, z = 123, true, "foo"
func main() {
var q, r = 789, false
r, s := true, "bar"
r = y // r is unused.
x = q // q is used.
}
example-unused.go
):
./example-unused.go:6:6: r declared and not used ./example-unused.go:7:16: s declared and not used
r
and s
to blank identifiers to avoid compilation errors.
package main
var x, y, z = 123, true, "foo"
func main() {
var q, r = 789, false
r, s := true, "bar"
r = y
x = q
_, _ = r, s // make r and s used.
}
var x, y = a+1, 5 // 8 5
var a, b, c = b+1, c+1, y // 7 6 5
y = 5
, c = y
, b = c+1
, a = b+1
, and x = a+1
.
+
symbol is the addition operator, which will be introduced in the next article.
var x, y = y, x
const a = -1.23
// The type of b is deduced as float64.
var b = a
// error: constant 1.23 truncated to integer.
var x = int32(a)
// error: cannot assign float64 to int32.
var y int32 = b
// okay: z == -1, and the type of z is int32.
// The fraction part of b is discarded.
var z = int32(b)
const k int16 = 255
// The type of n is deduced as int16.
var n = k
// error: constant 256 overflows uint8.
var f = uint8(k + 1)
// error: cannot assign int16 to uint8.
var g uint8 = n + 1
// okay: h == 0, and the type of h is uint8.
// n+1 overflows uint8 and is truncated.
var h = uint8(n + 1)
a
at line 3 is implicitly converted to its default type (float64
), so that the type of b
is deducted as float64
. More implicit conversion rules will be introduced in other articles later.
{
and }
to form a code block. A code block can nest other code blocks. A variable or a named constant declared in an inner code block will shadow the variables and constants declared with the same name in outer code blocks. For examples, the following program declares three distinct variables, all of them are called x
. An inner x
shadows an outer one.
package main
const y = 789
var x int = 123
func main() {
// The x variable shadows the above declared
// package-level variable x.
var x = true
// A nested code block.
{
// Here, the left x and y are both
// new declared variable. The right
// ones are declared in outer blocks.
x, y := x, y
// In this code block, the just new
// declared x and y shadow the outer
// declared same-name identifiers.
x, z := !x, y/10 // only z is new declared
y /= 100
println(x, y, z) // false 7 78
}
println(x) // true
println(z) // error: z is undefined.
}
main
function of the above example doesn't compile.
// 3 untyped named constants. Their bound
// values all overflow their respective
// default types. This is allowed.
const n = 1 << 64 // overflows int
const r = 'a' + 0x7FFFFFFF // overflows rune
const x = 2e+308 // overflows float64
func main() {
_ = n >> 2
_ = r - 0x7FFFFFFF
_ = x / 2
}
// 3 typed named constants. Their bound
// values are not allowed to overflow their
// respective default types. The 3 lines
// all fail to compile.
const n int = 1 << 64 // overflows int
const r rune = 'a' + 0x7FFFFFFF // overflows rune
const x float64 = 2e+308 // overflows float64
#define
macros in C. A constant declaration defines a named constant which represents a literal. All the occurrences of a named constant will be replaced with the literal it represents at compile time.
package main
const X = 3
const Y = X + X
var a = X
func main() {
b := Y
println(a, b, X, Y)
}
package main
var a = 3
func main() {
b := 6
println(a, b, 3, 6)
}
The Go 101 project is hosted on Github. Welcome to improve Go 101 articles by submitting corrections for all kinds of mistakes, such as typos, grammar errors, wording inaccuracies, description flaws, code bugs and broken links.
If you would like to learn some Go details and facts every serveral days, please follow Go 101's official Twitter account @zigo_101.
reflect
standard package.sync
standard package.sync/atomic
standard package.