package main
import "fmt"
import "io"
import inout "io"
func main() {
fmt.Println(&inout.EOF == &io.EOF) // true
}
default branch in switch and select blocks can be put before all case branches, after all case branches, or between case branches.
switch n := rand.Intn(3); n {
case 0: fmt.Println("n == 0")
case 1: fmt.Println("n == 1")
default: fmt.Println("n == 2")
}
switch n := rand.Intn(3); n {
default: fmt.Println("n == 2")
case 0: fmt.Println("n == 0")
case 1: fmt.Println("n == 1")
}
switch n := rand.Intn(3); n {
case 0: fmt.Println("n == 0")
default: fmt.Println("n == 2")
case 1: fmt.Println("n == 1")
}
var x, y chan int
select {
case <-x:
case y <- 1:
default:
}
select {
case <-x:
default:
case y <- 1:
}
select {
default:
case <-x:
case y <- 1:
}
switch block can't be duplicate, but boolean ones can.
package main
func main() {
switch 123 {
case 123:
case 123: // error: duplicate case
}
}
package main
func main() {
switch false {
case false:
case false:
}
}
switch block are always evaluated to typed values.
123 in the following switch block is viewed as a value of int instead of an untyped integer. So the following program fails to compile.
package main
func main() {
switch 123 {
case int64(123): // error: mismatched types
case uint32(789): // error: mismatched types
}
}
switch block is a typed value true of the predeclared type bool.
true.
package main
import "fmt"
func main() {
switch { // <=> switch true {
case true: fmt.Println("true")
case false: fmt.Println("false")
}
}
{ of an explicit code block can be put on the next line.
package main
func main() {
var i = 0
Outer:
for
{ %% okay on the next line
switch
{ %% okay on the next line
case i == 5:
break Outer
default:
i++
}
}
}
true or false? The answer is true. Please read line break rules in Go for reasons.
package main
import "fmt"
func False() bool {
return false
}
func main() {
switch False()
{
case true: fmt.Println("true")
case false: fmt.Println("false")
}
}
case branch blocks must be explicit.
func demo(n, m int) (r int) {
switch n {
case 123:
if m > 0 {
goto End
}
r++
End: // syntax error: missing statement after label
default:
r = 1
}
return
}
case branch code block should be explicit:
func demo(n, m int) (r int) {
switch n {
case 123: {
if m > 0 {
goto End
}
r++
End:
}
default:
r = 1
}
return
}
End::
func demo(n, m int) (r int) {
switch n {
case 123:
if m > 0 {
goto End
}
r++
End:;
default:
r = 1
}
return
}
package main
import "fmt"
func F() (r int) {
defer func() {
r = 789
}()
return 123 // <=> r = 123; return
}
func main() {
fmt.Println(F()) // 789
}
recover calls may be no-ops.
recover function at the right places. Please read the right places to call the built-in recover function for details.
os.Exit function call and exit a goroutine with a runtime.Goexit function call.
os.Exit function. An os.Exit function call takes an int code as argument and returns the code to operating system.
// exit-example.go
package main
import "os"
import "time"
func main() {
go func() {
time.Sleep(time.Second)
os.Exit(1)
}()
select{}
}
$ go run a.go exit status 1 $ echo $? 1
runtime.Goexit function. The runtime.Goexit function has no parameters.
Java word will not be printed.
package main
import "fmt"
import "runtime"
func main() {
c := make(chan int)
go func() {
defer func() {c <- 1}()
defer fmt.Println("Go")
func() {
defer fmt.Println("C")
runtime.Goexit()
}()
fmt.Println("Java")
}()
<-c
}
++ and the decrement -- is lower than the dereference operator * and the address-taking operator &, which are lower than the property selection operator . in selectors.
package main
import "fmt"
type T struct {
x int
y *int
}
func main() {
var t T
p := &t.x // <=> p := &(t.x)
fmt.Printf("%T\n", p) // *int
*p++ // <=> (*p)++
*p-- // <=> (*p)--
t.y = p
a := *t.y // <=> *(t.y)
fmt.Printf("%T\n", a) // int
}
package main
func main() {
}
const M = 2
// Compiles okay. 1.0 is deduced as an int value.
var _ = 1.0 << M
var N = 2
// Fails to compile. 1.0 is deduced as a float64 value.
var _ = 1.0 << N
package main
type MyInt int64
type Ta *int64
type Tb *MyInt
func main() {
var a Ta
var b Tb
// Direct conversion is not allowed.
//a = Ta(b) // error
// But indirect conversion is possible.
y := (*MyInt)(b)
x := (*int64)(y)
a = x // <=> the next line
a = (*int64)(y) // <=> the next line
a = (*int64)((*MyInt)(b))
_ = a
}
package main
import "fmt"
func main() {
a := struct{}{}
b := struct{}{}
x := struct{}{}
y := struct{}{}
m := [10]struct{}{}
n := [10]struct{}{}
o := [10]struct{}{}
p := [10]struct{}{}
fmt.Println(&x, &y, &o, &p)
// For the standard Go compiler (1.25.n),
// x, y, o and p escape to heap, but
// a, b, m and n are allocated on stack.
fmt.Println(&a == &b) // false
fmt.Println(&x == &y) // true
fmt.Println(&a == &x) // false
fmt.Println(&m == &n) // false
fmt.Println(&o == &p) // true
fmt.Println(&n == &p) // false
}
package main
func main() {
type P *P
var p P
p = &p
p = **************p
}
package main
func main() {
type S []S
type M map[string]M
type C chan C
type F func(F) F
s := S{0:nil}
s[0] = s
m := M{"Go": nil}
m["Go"] = m
c := make(C, 3)
c <- c; c <- c; c <- c
var f F
f = func(F)F {return f}
_ = s[0][0][0][0][0][0][0][0]
_ = m["Go"]["Go"]["Go"]["Go"]
<-<-<-c
f(f(f(f(f))))
}
package main
type T struct {
x int
}
func (T) m(){} // T has one method.
type P *T // a named one-level pointer type.
type PP *P // a named two-level pointer type.
func main() {
var t T
var tp = &t
var tpp = &tp
var p P = tp
var pp PP = &p
tp.x = 12 // okay
p.x = 34 // okay
pp.x = 56 // error: type PP has no field or method x
tpp.x = 78 // error: type **T has no field or method x
tp.m() // okay. Type *T also has a "m" method.
p.m() // error: type P has no field or method m
pp.m() // error: type PP has no field or method m
tpp.m() // error: type **T has no field or method m
}
Foo1 and the Foo2 functions are equivalent, but the function Foo2 is much tidier than the function Foo1.
func Foo1(m map[string]int) int {
if m != nil {
return m["foo"]
}
return 0
}
func Foo2(m map[string]int) int {
return m["foo"]
}
package main
func main() {
var m map[string]int // nil
delete(m, "foo")
}
append function call may share some elements with the original slice, or not.
package main
import "fmt"
func main() {
s := make([]int, 3, 9)
fmt.Println(len(s)) // 3
s2 := s[2:7]
fmt.Println(len(s2)) // 5
}
package main
import "fmt"
func main() {
var x []int // nil
a := x[:]
b := x[0:0]
c := x[:0:0]
// Print three "true".
fmt.Println(a == nil, b == nil, c == nil)
}
package main
func main() {
var s []int // nil
for range s {
}
var m map[string]int // nil
for range m {
}
}
01234.
package main
import "fmt"
func main() {
var a *[5]int // nil
for i, _ := range a {
fmt.Print(i)
}
}
var k = 1
// error: index must be non-negative integer constant
var x = [2]int{k: 1}
// error: index must be non-negative integer constant
var y = []int{k: 1}
// error: duplicate index in array literal: 1
var a = []bool{0: false, 1: true, 1: true}
// error: duplicate index in array literal: 0
var b = [...]string{0: "foo", 1: "bar", 0: "foo"}
// error: duplicate key "foo" in map literal
var c = map[string]int{"foo": 1, "foo": 2}
package main
func main() {
// Container composite literals are unaddressable.
// It is ok to take slice literal element addresses.
_ = &[]int{1}[0] // ok
// Cannot take addresses of array literal elements.
_ = &[5]int{}[0] // error
// It is ok to modify slice literal elements.
[]int{1,2,3}[1] = 9 // ok
// Cannot modify array literal elements.
[3]int{1,2,3}[1] = 9 // error
}
package main
func main() {
// Map elements are unaddressable in Go.
// The following lines compile okay. Deriving
// slices from unaddressable slices is allowed.
_ = []int{6, 7, 8, 9}[1:3]
var ms = map[string][]int{"abc": {0, 1, 2, 3}}
_ = ms["abc"][1:3]
// The following lines fail to compile. Deriving
// slices from unaddressable arrays is not allowed.
/*
_ = [...]int{6, 7, 8, 9}[1:3] // error
var ma = map[string][4]int{"abc": {0, 1, 2, 3}}
_ = ma["abc"][1:3] // error
*/
}
NaN as keys to a map is like putting the entries in a black hole.
NaN != NaN, which is another detail will be described below. Before Go 1.12, the elements with NaN as keys can only be found out in a for-range loop, Since Go 1.12, the elements with NaN as keys can also be printed out by fmt.Print alike functions.
package main
import "fmt"
import "math"
func main() {
var a = math.NaN()
fmt.Println(a) // NaN
var m = map[float64]int{}
m[a] = 123
v, present := m[a]
fmt.Println(v, present) // 0 false
m[a] = 789
v, present = m[a]
fmt.Println(v, present) // 0 false
fmt.Println(m) // map[NaN:789 NaN:123]
delete(m, a) // no-op
fmt.Println(m) // map[NaN:789 NaN:123]
for k, v := range m {
fmt.Println(k, v)
}
// the above loop outputs:
// NaN 123
// NaN 789
}
fmt.Println(m) calls both printed map[NaN:<nil> NaN:<nil>].
fmt.Println line is removed, the outputs of the two lines before it print the same value 5; otherwise, one print 5 and one print 8 (for the standard Go compiler 1.25.n).
package main
import "fmt"
func main() {
s := "abcde"
x := []byte(s) // len(s) == 1
fmt.Println(cap([]byte(s))) // 32
fmt.Println(cap(x)) // 8
fmt.Println(x)
}
s, the loop for i = range s {...} is not equivalent to the loop for i = 0; i < len(s); i++ {...}.
i may be different for the two loops.
package main
import "fmt"
var i int
func fa(s []int, n int) int {
i = n
for i = 0; i < len(s); i++ {}
return i
}
func fb(s []int, n int) int {
i = n
for i = range s {}
return i
}
func main() {
s := []int{2, 3, 5, 7, 11, 13}
fmt.Println(fa(s, -1), fb(s, -1)) // 6 5
s = nil
fmt.Println(fa(s, -1), fb(s, -1)) // 0 -1
}
package main
import "fmt"
func f(m map[byte]byte) string {
bs := make([]byte, 0, 2*len(m))
for k, v := range m {
bs = append(bs, k, v)
}
return string(bs)
}
func main() {
m := map[byte]byte{'a':'A', 'b':'B', 'c':'C'}
s0 := f(m)
for i := 1; ; i++{
if s := f(m); s != s0 {
fmt.Println(s0)
fmt.Println(s)
fmt.Println(i)
return
}
}
}
fmt package) also results sorted entries.
package main
import "fmt"
func main() {
m := map[int]int{0: 0, 1: 100, 2: 200}
r, n, i:= len(m), len(m), 0
for range m {
m[n] = n*100
n++
i++
}
fmt.Printf("%d new entries, iterate %d and skip %d\n",
i, i - r, n - i,
)
}
package main
func main() {
var x interface{} = []int{}
_ = x == x // panic
}
package main
type Foo interface {
foo()
}
type T int
func (T) foo() {}
func main() {
var x interface{} = T(123)
// The following two lines fails to compile, for the
// same reason: interface{} does not implement Foo.
/*
var _ Foo = x // error
var _ = Foo(x) // error
*/
// But the following line compiles and runs okay.
var _ = x.(Foo) // okay
}
package main
func main() {
var x interface{} = true
// Assertion fails, but doesn't cause a panic.
_, _ = x.(int)
// Assertion fails, which causes a panic.
_ = x.(int)
}
package main
type Ia interface {
m()
}
type Ib interface {
m() int
}
type T struct{}
func (T) m() {}
func main() {
var x Ia = T{}
_ = x.(Ib) // panic: main.T is not main.Ib
}
go vet command warns on such assertions.
error values returned by two errors.New calls with the same argument are not equal.
errors.New function will copy the input string argument and use a pointer to the copied string as the dynamic value of the returned error value. Two different calls will produce two different pointers.
package main
import "fmt"
import "errors"
func main() {
notfound := "not found"
a, b := errors.New(notfound), errors.New(notfound)
fmt.Println(a == b) // false
}
package main
func main() {
}
func foo(c <-chan int) {
close(c) // error: cannot close receive-only channel
}
case branch gets selected, it will produce a panic at run time.
package main
func main() {
var c = make(chan bool)
close(c)
select {
case <-c:
case c <- true: // panic: send on closed channel
default:
}
}
package main
func main() {
type T struct{}
type S = []int
}
package main
import "fmt"
import "math"
func main() {
var a = math.Sqrt(-1.0)
fmt.Println(a) // NaN
fmt.Println(a == a) // false
var x = 0.0
var y = 1.0 / x
var z = 2.0 * y
fmt.Println(y, z, y == z) // +Inf +Inf true
}
foo:
package foo
type I = interface {
about() string
}
type S struct {
a string
}
func (s S) about() string {
return s.a
}
bar:
package bar
type I = interface {
about() string
}
type S struct {
a string
}
func (s S) about() string {
return s.a
}
S from the two packages can't be converted to each other.
S from the two packages denote two distinct method sets.
foo.S doesn't implement the interface type bar.I.
bar.S doesn't implement the interface type foo.I.
package main
import "包2/foo"
import "包2/bar"
func main() {
var x foo.S
var y bar.S
var _ foo.I = x
var _ bar.I = y
// The following lines fail to compile.
x = foo.S(y)
y = bar.S(x)
var _ foo.I = y
var _ bar.I = x
}
_. The following program will print true.
package main
import "fmt"
type T struct {
_ int
_ bool
}
func main() {
var t1 = T{123, true}
var t2 = T{789, false}
fmt.Println(t1 == t2) // true
}
package main
type T struct{x, y int}
func main() {
// Each of the following three lines makes code
// fail to compile. Some "{}"s confuse compilers.
/*
if T{} == T{123, 789} {}
if T{} == (T{123, 789}) {}
if (T{}) == T{123, 789} {}
var _ = func()(nil) // nil is viewed as a type
*/
// We must add parentheses like the following
// two lines to make code compile okay.
if (T{} == T{123, 789}) {}
if (T{}) == (T{123, 789}) {}
var _ = (func())(nil) // nil is viewed as a value
}
package main
func f() {
f()
}
func main() {
defer func() {
recover() // helpless to avoid program crashing
}()
f()
}
runtime: goroutine stack exceeds 1000000000-byte limit fatal error: stack overflow runtime stack: ...
reflect.DeepEqual(x, y) and x == y may be different.
reflect.DeepEqual(x, y) will always return false if the types of its two arguments are different, whereas x == y may return true even if the types of the two operands are different.
DeepEqual call with two pointer argument values of the same type returns whether or not the two respective values referenced by the two pointers are deep equal. So the call might return true even if the two pointers are not equal.
DeepEqual call might return true if both of its arguments are in cyclic reference chains (to avoid infinite looping in the call).
reflect.DeepEqual(x, y) is not expected to panic generally, whereas x == y will panic if the two operands are both interface values and their dynamic types are identical and incomparable.
package main
import (
"fmt"
"reflect"
)
func main() {
type Book struct {page int}
x := struct {page int}{123}
y := Book{123}
fmt.Println(reflect.DeepEqual(x, y)) // false
fmt.Println(x == y) // true
z := Book{123}
fmt.Println(reflect.DeepEqual(&z, &y)) // true
fmt.Println(&z == &y) // false
type Node struct{peer *Node}
var q, r, s Node
q.peer = &q // form a cyclic reference chain
r.peer = &s // form a cyclic reference chain
s.peer = &r
println(reflect.DeepEqual(&q, &r)) // true
fmt.Println(q == r) // false
var f1, f2 func() = nil, func(){}
fmt.Println(reflect.DeepEqual(f1, f1)) // true
fmt.Println(reflect.DeepEqual(f2, f2)) // false
var a, b interface{} = []int{1, 2}, []int{1, 2}
fmt.Println(reflect.DeepEqual(a, b)) // true
fmt.Println(a == b) // panic
}
DeepEqual call are both function values, then the call returns true only if the two function arguments are both nil and their types are identical. It is similar to compare container values whose elements contain function values or compare struct values whose fields contain function values. But please also note that the result of comparing two slices (of the same type) is always true if the two slices exactly share the same elements (in other words, they have the same length and each pair of their corresponding elements have the same address). An example:
package main
import (
"fmt"
"reflect"
)
func main() {
a := [1]func(){func(){}}
b := a
fmt.Println(reflect.DeepEqual(a, a)) // false
fmt.Println(reflect.DeepEqual(a[:], a[:])) // true
fmt.Println(reflect.DeepEqual(a[:], b[:])) // false
a[0], b[0] = nil, nil
fmt.Println(reflect.DeepEqual(a[:], b[:])) // true
}
reflect.Value.Bytes() method returns a []byte value, which element type, byte, might be not the same as the Go slice value represented by the receiver parameter.
MyByte is the predeclared type byte, we know that Go type system forbids the conversions between []MyByte and []byte values. However, it looks the implementation of the method Bytes of the reflect.Value type partially violates this restriction unintentionally, by allowing converting a []MyByte value to []byte.
package main
import "bytes"
import "fmt"
import "reflect"
type MyByte byte
func main() {
var mybs = []MyByte{'a', 'b', 'c'}
var bs []byte
// bs = []byte(mybs) // this line fails to compile
v := reflect.ValueOf(mybs)
bs = v.Bytes() // okay. Violating Go type system.
fmt.Println(bytes.HasPrefix(bs, []byte{'a', 'b'})) // true
bs[1], bs[2] = 'r', 't'
fmt.Printf("%s \n", mybs) // art
}
bytes standard package for the []MyByte values.
reflect.Value.Bytes() method might be removed later.
os.IsNotExist(err) instead of err == os.ErrNotExist to check whether or not a file exists.
err == os.ErrNotExist may miss errors.
package main
import (
"fmt"
"os"
)
func main() {
_, err := os.Stat("a-nonexistent-file.abcxyz")
fmt.Println(os.IsNotExist(err)) // true
fmt.Println(err == os.ErrNotExist) // false
}
errors.Is(err, os.ErrNotExist) is more recommended to be used to check whether or not a file exists.
package main
import (
"errors"
"fmt"
"os"
)
func main() {
_, err := os.Stat("a-nonexistent-file.abcxyz")
fmt.Println(errors.Is(err, os.ErrNotExist)) // true
}
flag standard package treats boolean command flags differently than integer and string flags.
-flag, for boolean flags only.
-flag=x, for any flag.
-flag x, for non-boolean flags only.
package main
import "fmt"
import "flag"
var b = flag.Bool("b", true, "a boolean flag")
var i = flag.Int("i", 123, "an integer flag")
var s = flag.String("s", "hi", "a string flag")
func main() {
flag.Parse()
fmt.Print("b=", *b, ", i=", *i, ", s=", *s, "\n")
fmt.Println("arguments:", flag.Args())
}
./exampleProgram -b false -i 789 -s bye arg0 arg1
b=true, i=123, s=hi arguments: [false -i 789 -s bye arg0 arg1]
./exampleProgram -b=false -i 789 -s bye arg0 arg1
./exampleProgram -i 789 -s bye -b arg0 arg1
b=true, i=789, s=bye arguments: [arg0 arg1]
[Sp|Fp|P]rintf functions support positional arguments.
coco.
package main
import "fmt"
func main() {
// The next line prints: coco
fmt.Printf("%[2]v%[1]v%[2]v%[1]v", "o", "c")
}
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.