github.com/tinygo-org/tinygo@v0.31.3-0.20240404173401-90b0bf646c27/testdata/interface.go (about) 1 package main 2 3 import "time" 4 5 func main() { 6 thing := &Thing{"foo"} 7 println("thing:", thing.String()) 8 thing.Print() 9 printItf(5) 10 printItf(byte('x')) 11 printItf("foo") 12 printItf(Foo(18)) 13 printItf(*thing) 14 printItf(thing) 15 printItf(Stringer(thing)) 16 printItf(struct{ n int }{}) 17 printItf(struct { 18 n int `foo:"bar"` 19 }{}) 20 printItf(Number(3)) 21 array := Array([4]uint32{1, 7, 11, 13}) 22 printItf(array) 23 printItf(ArrayStruct{3, array}) 24 printItf(SmallPair{3, 5}) 25 s := Stringer(thing) 26 println("Stringer.String():", s.String()) 27 var itf interface{} = s 28 println("Stringer.(*Thing).String():", itf.(Stringer).String()) 29 if s, ok := s.(interface{ String() string }); ok { 30 println("s has String() method:", s.String()) 31 } 32 33 println("nested switch:", nestedSwitch('v', 3)) 34 35 // Try putting a linked list in an interface: 36 // https://github.com/tinygo-org/tinygo/issues/309 37 itf = linkedList{} 38 39 // Test bugfix for assertion on named empty interface: 40 // https://github.com/tinygo-org/tinygo/issues/453 41 _, _ = itf.(Empty) 42 43 var v Byter = FooByte(3) 44 println("Byte(): ", v.Byte()) 45 46 var n int 47 var f float32 48 var interfaceEqualTests = []struct { 49 equal bool 50 lhs interface{} 51 rhs interface{} 52 }{ 53 {true, true, true}, 54 {true, int(1), int(1)}, 55 {true, int8(1), int8(1)}, 56 {true, int16(1), int16(1)}, 57 {true, int32(1), int32(1)}, 58 {true, int64(1), int64(1)}, 59 {true, uint(1), uint(1)}, 60 {false, uint(1), uint(2)}, 61 {true, uint8(1), uint8(1)}, 62 {true, uint16(1), uint16(1)}, 63 {true, uint32(1), uint32(1)}, 64 {true, uint64(1), uint64(1)}, 65 {true, uintptr(1), uintptr(1)}, 66 {true, float32(1.1), float32(1.1)}, 67 {true, float64(1.1), float64(1.1)}, 68 {true, complex(100, 8), complex(100, 8)}, 69 {false, complex(100, 8), complex(101, 8)}, 70 {false, complex(100, 8), complex(100, 9)}, 71 {true, complex64(8), complex64(8)}, 72 {true, complex128(8), complex128(8)}, 73 {true, "string", "string"}, 74 {false, "string", "stringx"}, 75 {true, [2]int16{-5, 201}, [2]int16{-5, 201}}, 76 {false, [2]int16{-5, 201}, [2]int16{-5, 202}}, 77 {false, [2]int16{-5, 201}, [2]int16{5, 201}}, 78 {true, &n, &n}, 79 {false, &n, new(int)}, 80 {false, new(int), new(int)}, 81 {false, &n, &f}, 82 {true, struct { 83 a int 84 b int 85 }{3, 5}, struct { 86 a int 87 b int 88 }{3, 5}}, 89 {false, struct { 90 a int 91 b int 92 }{3, 5}, struct { 93 a int 94 b int 95 }{3, 6}}, 96 {true, named1(), named1()}, 97 {true, named2(), named2()}, 98 {false, named1(), named2()}, 99 {false, named2(), named3()}, 100 {true, namedptr1(), namedptr1()}, 101 {false, namedptr1(), namedptr2()}, 102 } 103 for i, tc := range interfaceEqualTests { 104 if (tc.lhs == tc.rhs) != tc.equal { 105 println("test", i, "of interfaceEqualTests failed") 106 } 107 } 108 109 // test interface blocking 110 blockDynamic(NonBlocker{}) 111 println("non-blocking call on sometimes-blocking interface") 112 blockDynamic(SleepBlocker(time.Millisecond)) 113 println("slept 1ms") 114 blockStatic(SleepBlocker(time.Millisecond)) 115 println("slept 1ms") 116 117 // check that pointer-to-pointer type switches work 118 ptrptrswitch() 119 120 // check that type asserts to interfaces with no methods work 121 emptyintfcrash() 122 } 123 124 func printItf(val interface{}) { 125 switch val := val.(type) { 126 case Unmatched: 127 panic("matched the unmatchable") 128 case Doubler: 129 println("is Doubler:", val.Double()) 130 case Tuple: 131 println("is Tuple:", val.Nth(0), val.Nth(1), val.Nth(2), val.Nth(3)) 132 val.Print() 133 case int: 134 println("is int:", val) 135 case byte: 136 println("is byte:", val) 137 case string: 138 println("is string:", val) 139 case Thing: 140 println("is Thing:", val.String()) 141 case *Thing: 142 println("is *Thing:", val.String()) 143 case struct{ i int }: 144 println("is struct{i int}") 145 case struct{ n int }: 146 println("is struct{n int}") 147 case struct { 148 n int `foo:"bar"` 149 }: 150 println("is struct{n int `foo:\"bar\"`}") 151 case Foo: 152 println("is Foo:", val) 153 default: 154 println("is ?") 155 } 156 } 157 158 var ( 159 // Test for type assert support in the interp package. 160 globalThing interface{} = Foo(3) 161 _ = globalThing.(Foo) 162 ) 163 164 func nestedSwitch(verb rune, arg interface{}) bool { 165 switch verb { 166 case 'v', 's': 167 switch arg.(type) { 168 case int: 169 return true 170 } 171 } 172 return false 173 } 174 175 func blockDynamic(blocker DynamicBlocker) { 176 blocker.Block() 177 } 178 179 func blockStatic(blocker StaticBlocker) { 180 blocker.Sleep() 181 } 182 183 type Thing struct { 184 name string 185 } 186 187 func (t Thing) String() string { 188 return t.name 189 } 190 191 func (t Thing) Print() { 192 println("Thing.Print:", t.name) 193 } 194 195 type Stringer interface { 196 String() string 197 } 198 199 type Foo int 200 201 type Number int 202 203 func (n Number) Double() int { 204 return int(n) * 2 205 } 206 207 type Doubler interface { 208 Double() int 209 } 210 211 type Tuple interface { 212 Nth(int) uint32 213 Print() 214 } 215 216 type Array [4]uint32 217 218 func (a Array) Nth(n int) uint32 { 219 return a[n] 220 } 221 222 func (a Array) Print() { 223 println("Array len:", len(a)) 224 } 225 226 type ArrayStruct struct { 227 n int 228 a Array 229 } 230 231 func (a ArrayStruct) Nth(n int) uint32 { 232 return a.a[n] 233 } 234 235 func (a ArrayStruct) Print() { 236 println("ArrayStruct.Print:", len(a.a), a.n) 237 } 238 239 type SmallPair struct { 240 a byte 241 b byte 242 } 243 244 func (p SmallPair) Nth(n int) uint32 { 245 return uint32(int(p.a)*n + int(p.b)*n) 246 } 247 248 func (p SmallPair) Print() { 249 println("SmallPair.Print:", p.a, p.b) 250 } 251 252 // There is no type that matches this method. 253 type Unmatched interface { 254 NeverImplementedMethod() 255 } 256 257 type linkedList struct { 258 addr *linkedList 259 } 260 261 type DynamicBlocker interface { 262 Block() 263 } 264 265 type NonBlocker struct{} 266 267 func (b NonBlocker) Block() {} 268 269 type SleepBlocker time.Duration 270 271 func (s SleepBlocker) Block() { 272 time.Sleep(time.Duration(s)) 273 } 274 275 func (s SleepBlocker) Sleep() { 276 s.Block() 277 } 278 279 type StaticBlocker interface { 280 Sleep() 281 } 282 283 type Empty interface{} 284 285 type FooByte int 286 287 func (f FooByte) Byte() byte { return byte(f) } 288 289 type Byter interface { 290 Byte() uint8 291 } 292 293 // Make sure that named types inside functions do not alias with any other named 294 // functions. 295 296 type named int 297 298 func named1() any { 299 return named(0) 300 } 301 302 func named2() any { 303 type named int 304 return named(0) 305 } 306 307 func named3() any { 308 type named int 309 return named(0) 310 } 311 312 func namedptr1() interface{} { 313 type Test int 314 return (*Test)(nil) 315 } 316 317 func namedptr2() interface{} { 318 type Test byte 319 return (*Test)(nil) 320 } 321 322 func ptrptrswitch() { 323 identify(0) 324 identify(new(int)) 325 identify(new(*int)) 326 } 327 328 func identify(itf any) { 329 switch itf.(type) { 330 case int: 331 println("type is int") 332 case *int: 333 println("type is *int") 334 case **int: 335 println("type is **int") 336 default: 337 println("other type??") 338 } 339 } 340 341 func emptyintfcrash() { 342 if x, ok := any(5).(any); ok { 343 println("x is", x.(int)) 344 } 345 }