github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/test/range.go (about) 1 // run 2 3 // Copyright 2009 The Go Authors. All rights reserved. 4 // Use of this source code is governed by a BSD-style 5 // license that can be found in the LICENSE file. 6 7 // Test the 'for range' construct. 8 9 package main 10 11 // test range over channels 12 13 func gen(c chan int, lo, hi int) { 14 for i := lo; i <= hi; i++ { 15 c <- i 16 } 17 close(c) 18 } 19 20 func seq(lo, hi int) chan int { 21 c := make(chan int) 22 go gen(c, lo, hi) 23 return c 24 } 25 26 func testchan() { 27 s := "" 28 for i := range seq('a', 'z') { 29 s += string(i) 30 } 31 if s != "abcdefghijklmnopqrstuvwxyz" { 32 println("Wanted lowercase alphabet; got", s) 33 panic("fail") 34 } 35 } 36 37 // test that range over slice only evaluates 38 // the expression after "range" once. 39 40 var nmake = 0 41 42 func makeslice() []int { 43 nmake++ 44 return []int{1, 2, 3, 4, 5} 45 } 46 47 func testslice() { 48 s := 0 49 nmake = 0 50 for _, v := range makeslice() { 51 s += v 52 } 53 if nmake != 1 { 54 println("range called makeslice", nmake, "times") 55 panic("fail") 56 } 57 if s != 15 { 58 println("wrong sum ranging over makeslice", s) 59 panic("fail") 60 } 61 62 x := []int{10, 20} 63 y := []int{99} 64 i := 1 65 for i, x[i] = range y { 66 break 67 } 68 if i != 0 || x[0] != 10 || x[1] != 99 { 69 println("wrong parallel assignment", i, x[0], x[1]) 70 panic("fail") 71 } 72 } 73 74 func testslice1() { 75 s := 0 76 nmake = 0 77 for i := range makeslice() { 78 s += i 79 } 80 if nmake != 1 { 81 println("range called makeslice", nmake, "times") 82 panic("fail") 83 } 84 if s != 10 { 85 println("wrong sum ranging over makeslice", s) 86 panic("fail") 87 } 88 } 89 90 // test that range over array only evaluates 91 // the expression after "range" once. 92 93 func makearray() [5]int { 94 nmake++ 95 return [5]int{1, 2, 3, 4, 5} 96 } 97 98 func testarray() { 99 s := 0 100 nmake = 0 101 for _, v := range makearray() { 102 s += v 103 } 104 if nmake != 1 { 105 println("range called makearray", nmake, "times") 106 panic("fail") 107 } 108 if s != 15 { 109 println("wrong sum ranging over makearray", s) 110 panic("fail") 111 } 112 } 113 114 func testarray1() { 115 s := 0 116 nmake = 0 117 for i := range makearray() { 118 s += i 119 } 120 if nmake != 1 { 121 println("range called makearray", nmake, "times") 122 panic("fail") 123 } 124 if s != 10 { 125 println("wrong sum ranging over makearray", s) 126 panic("fail") 127 } 128 } 129 130 func makearrayptr() *[5]int { 131 nmake++ 132 return &[5]int{1, 2, 3, 4, 5} 133 } 134 135 func testarrayptr() { 136 nmake = 0 137 x := len(makearrayptr()) 138 if x != 5 || nmake != 1 { 139 println("len called makearrayptr", nmake, "times and got len", x) 140 panic("fail") 141 } 142 nmake = 0 143 x = cap(makearrayptr()) 144 if x != 5 || nmake != 1 { 145 println("cap called makearrayptr", nmake, "times and got len", x) 146 panic("fail") 147 } 148 s := 0 149 nmake = 0 150 for _, v := range makearrayptr() { 151 s += v 152 } 153 if nmake != 1 { 154 println("range called makearrayptr", nmake, "times") 155 panic("fail") 156 } 157 if s != 15 { 158 println("wrong sum ranging over makearrayptr", s) 159 panic("fail") 160 } 161 } 162 163 func testarrayptr1() { 164 s := 0 165 nmake = 0 166 for i := range makearrayptr() { 167 s += i 168 } 169 if nmake != 1 { 170 println("range called makearrayptr", nmake, "times") 171 panic("fail") 172 } 173 if s != 10 { 174 println("wrong sum ranging over makearrayptr", s) 175 panic("fail") 176 } 177 } 178 179 // test that range over string only evaluates 180 // the expression after "range" once. 181 182 func makestring() string { 183 nmake++ 184 return "abcd☺" 185 } 186 187 func teststring() { 188 var s rune 189 nmake = 0 190 for _, v := range makestring() { 191 s += v 192 } 193 if nmake != 1 { 194 println("range called makestring", nmake, "times") 195 panic("fail") 196 } 197 if s != 'a'+'b'+'c'+'d'+'☺' { 198 println("wrong sum ranging over makestring", s) 199 panic("fail") 200 } 201 } 202 203 func teststring1() { 204 s := 0 205 nmake = 0 206 for i := range makestring() { 207 s += i 208 } 209 if nmake != 1 { 210 println("range called makestring", nmake, "times") 211 panic("fail") 212 } 213 if s != 10 { 214 println("wrong sum ranging over makestring", s) 215 panic("fail") 216 } 217 } 218 219 // test that range over map only evaluates 220 // the expression after "range" once. 221 222 func makemap() map[int]int { 223 nmake++ 224 return map[int]int{0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: '☺'} 225 } 226 227 func testmap() { 228 s := 0 229 nmake = 0 230 for _, v := range makemap() { 231 s += v 232 } 233 if nmake != 1 { 234 println("range called makemap", nmake, "times") 235 panic("fail") 236 } 237 if s != 'a'+'b'+'c'+'d'+'☺' { 238 println("wrong sum ranging over makemap", s) 239 panic("fail") 240 } 241 } 242 243 func testmap1() { 244 s := 0 245 nmake = 0 246 for i := range makemap() { 247 s += i 248 } 249 if nmake != 1 { 250 println("range called makemap", nmake, "times") 251 panic("fail") 252 } 253 if s != 10 { 254 println("wrong sum ranging over makemap", s) 255 panic("fail") 256 } 257 } 258 259 // test that range evaluates the index and value expressions 260 // exactly once per iteration. 261 262 var ncalls = 0 263 264 func getvar(p *int) *int { 265 ncalls++ 266 return p 267 } 268 269 func testcalls() { 270 var i, v int 271 si := 0 272 sv := 0 273 for *getvar(&i), *getvar(&v) = range [2]int{1, 2} { 274 si += i 275 sv += v 276 } 277 if ncalls != 4 { 278 println("wrong number of calls:", ncalls, "!= 4") 279 panic("fail") 280 } 281 if si != 1 || sv != 3 { 282 println("wrong sum in testcalls", si, sv) 283 panic("fail") 284 } 285 286 ncalls = 0 287 for *getvar(&i), *getvar(&v) = range [0]int{} { 288 println("loop ran on empty array") 289 panic("fail") 290 } 291 if ncalls != 0 { 292 println("wrong number of calls:", ncalls, "!= 0") 293 panic("fail") 294 } 295 } 296 297 func main() { 298 testchan() 299 testarray() 300 testarray1() 301 testarrayptr() 302 testarrayptr1() 303 testslice() 304 testslice1() 305 teststring() 306 teststring1() 307 testmap() 308 testmap1() 309 testcalls() 310 }