// run | |
// Copyright 2009 The Go Authors. All rights reserved. | |
// Use of this source code is governed by a BSD-style | |
// license that can be found in the LICENSE file. | |
// Test nil. | |
package main | |
import ( | |
"fmt" | |
"time" | |
) | |
type T struct { | |
i int | |
} | |
type IN interface{} | |
func main() { | |
var i *int | |
var f *float32 | |
var s *string | |
var m map[float32]*int | |
var c chan int | |
var t *T | |
var in IN | |
var ta []IN | |
i = nil | |
f = nil | |
s = nil | |
m = nil | |
c = nil | |
t = nil | |
i = nil | |
ta = make([]IN, 1) | |
ta[0] = nil | |
_, _, _, _, _, _, _, _ = i, f, s, m, c, t, in, ta | |
arraytest() | |
chantest() | |
maptest() | |
slicetest() | |
} | |
func shouldPanic(f func()) { | |
defer func() { | |
if recover() == nil { | |
panic("not panicking") | |
} | |
}() | |
f() | |
} | |
func shouldBlock(f func()) { | |
go func() { | |
f() | |
panic("did not block") | |
}() | |
time.Sleep(1e7) | |
} | |
// nil array pointer | |
func arraytest() { | |
var p *[10]int | |
// Looping over indices is fine. | |
s := 0 | |
for i := range p { | |
s += i | |
} | |
if s != 45 { | |
panic(s) | |
} | |
s = 0 | |
for i := 0; i < len(p); i++ { | |
s += i | |
} | |
if s != 45 { | |
panic(s) | |
} | |
// Looping over values is not. | |
shouldPanic(func() { | |
for i, v := range p { | |
s += i + v | |
} | |
}) | |
shouldPanic(func() { | |
for i := 0; i < len(p); i++ { | |
s += p[i] | |
} | |
}) | |
} | |
// nil channel | |
// select tests already handle select on nil channel | |
func chantest() { | |
var ch chan int | |
// nil channel is never ready | |
shouldBlock(func() { | |
ch <- 1 | |
}) | |
shouldBlock(func() { | |
<-ch | |
}) | |
shouldBlock(func() { | |
x, ok := <-ch | |
println(x, ok) // unreachable | |
}) | |
if len(ch) != 0 { | |
panic(len(ch)) | |
} | |
if cap(ch) != 0 { | |
panic(cap(ch)) | |
} | |
} | |
// nil map | |
func maptest() { | |
var m map[int]int | |
// nil map appears empty | |
if len(m) != 0 { | |
panic(len(m)) | |
} | |
if m[1] != 0 { | |
panic(m[1]) | |
} | |
if x, ok := m[1]; x != 0 || ok { | |
panic(fmt.Sprint(x, ok)) | |
} | |
for k, v := range m { | |
panic(k) | |
panic(v) | |
} | |
// can delete (non-existent) entries | |
delete(m, 2) | |
// but cannot be written to | |
shouldPanic(func() { | |
m[2] = 3 | |
}) | |
} | |
// nil slice | |
func slicetest() { | |
var x []int | |
// nil slice is just a 0-element slice. | |
if len(x) != 0 { | |
panic(len(x)) | |
} | |
if cap(x) != 0 { | |
panic(cap(x)) | |
} | |
// no 0-element slices can be read from or written to | |
var s int | |
shouldPanic(func() { | |
s += x[1] | |
}) | |
shouldPanic(func() { | |
x[2] = s | |
}) | |
} |