|  | // 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 | 
|  | }) | 
|  | } |