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