package main import "time" func main() { thing := &Thing{"foo"} println("thing:", thing.String()) thing.Print() printItf(5) printItf(byte('x')) printItf("foo") printItf(Foo(18)) printItf(*thing) printItf(thing) printItf(Stringer(thing)) printItf(struct{ n int }{}) printItf(struct { n int `foo:"bar"` }{}) printItf(Number(3)) array := Array([4]uint32{1, 7, 11, 13}) printItf(array) printItf(ArrayStruct{3, array}) printItf(SmallPair{3, 5}) s := Stringer(thing) println("Stringer.String():", s.String()) var itf interface{} = s println("Stringer.(*Thing).String():", itf.(Stringer).String()) if s, ok := s.(interface{ String() string }); ok { println("s has String() method:", s.String()) } println("nested switch:", nestedSwitch('v', 3)) // Try putting a linked list in an interface: // https://github.com/tinygo-org/tinygo/issues/309 itf = linkedList{} // Test bugfix for assertion on named empty interface: // https://github.com/tinygo-org/tinygo/issues/453 _, _ = itf.(Empty) var v Byter = FooByte(3) println("Byte(): ", v.Byte()) var n int var f float32 var interfaceEqualTests = []struct { equal bool lhs interface{} rhs interface{} }{ {true, true, true}, {true, int(1), int(1)}, {true, int8(1), int8(1)}, {true, int16(1), int16(1)}, {true, int32(1), int32(1)}, {true, int64(1), int64(1)}, {true, uint(1), uint(1)}, {false, uint(1), uint(2)}, {true, uint8(1), uint8(1)}, {true, uint16(1), uint16(1)}, {true, uint32(1), uint32(1)}, {true, uint64(1), uint64(1)}, {true, uintptr(1), uintptr(1)}, {true, float32(1.1), float32(1.1)}, {true, float64(1.1), float64(1.1)}, {true, complex(100, 8), complex(100, 8)}, {false, complex(100, 8), complex(101, 8)}, {false, complex(100, 8), complex(100, 9)}, {true, complex64(8), complex64(8)}, {true, complex128(8), complex128(8)}, {true, "string", "string"}, {false, "string", "stringx"}, {true, [2]int16{-5, 201}, [2]int16{-5, 201}}, {false, [2]int16{-5, 201}, [2]int16{-5, 202}}, {false, [2]int16{-5, 201}, [2]int16{5, 201}}, {true, &n, &n}, {false, &n, new(int)}, {false, new(int), new(int)}, {false, &n, &f}, {true, struct { a int b int }{3, 5}, struct { a int b int }{3, 5}}, {false, struct { a int b int }{3, 5}, struct { a int b int }{3, 6}}, {true, named1(), named1()}, {true, named2(), named2()}, {false, named1(), named2()}, {false, named2(), named3()}, {true, namedptr1(), namedptr1()}, {false, namedptr1(), namedptr2()}, } for i, tc := range interfaceEqualTests { if (tc.lhs == tc.rhs) != tc.equal { println("test", i, "of interfaceEqualTests failed") } } // test interface blocking blockDynamic(NonBlocker{}) println("non-blocking call on sometimes-blocking interface") blockDynamic(SleepBlocker(time.Millisecond)) println("slept 1ms") blockStatic(SleepBlocker(time.Millisecond)) println("slept 1ms") // check that pointer-to-pointer type switches work ptrptrswitch() } func printItf(val interface{}) { switch val := val.(type) { case Unmatched: panic("matched the unmatchable") case Doubler: println("is Doubler:", val.Double()) case Tuple: println("is Tuple:", val.Nth(0), val.Nth(1), val.Nth(2), val.Nth(3)) val.Print() case int: println("is int:", val) case byte: println("is byte:", val) case string: println("is string:", val) case Thing: println("is Thing:", val.String()) case *Thing: println("is *Thing:", val.String()) case struct{ i int }: println("is struct{i int}") case struct{ n int }: println("is struct{n int}") case struct { n int `foo:"bar"` }: println("is struct{n int `foo:\"bar\"`}") case Foo: println("is Foo:", val) default: println("is ?") } } var ( // Test for type assert support in the interp package. globalThing interface{} = Foo(3) _ = globalThing.(Foo) ) func nestedSwitch(verb rune, arg interface{}) bool { switch verb { case 'v', 's': switch arg.(type) { case int: return true } } return false } func blockDynamic(blocker DynamicBlocker) { blocker.Block() } func blockStatic(blocker StaticBlocker) { blocker.Sleep() } type Thing struct { name string } func (t Thing) String() string { return t.name } func (t Thing) Print() { println("Thing.Print:", t.name) } type Stringer interface { String() string } type Foo int type Number int func (n Number) Double() int { return int(n) * 2 } type Doubler interface { Double() int } type Tuple interface { Nth(int) uint32 Print() } type Array [4]uint32 func (a Array) Nth(n int) uint32 { return a[n] } func (a Array) Print() { println("Array len:", len(a)) } type ArrayStruct struct { n int a Array } func (a ArrayStruct) Nth(n int) uint32 { return a.a[n] } func (a ArrayStruct) Print() { println("ArrayStruct.Print:", len(a.a), a.n) } type SmallPair struct { a byte b byte } func (p SmallPair) Nth(n int) uint32 { return uint32(int(p.a)*n + int(p.b)*n) } func (p SmallPair) Print() { println("SmallPair.Print:", p.a, p.b) } // There is no type that matches this method. type Unmatched interface { NeverImplementedMethod() } type linkedList struct { addr *linkedList } type DynamicBlocker interface { Block() } type NonBlocker struct{} func (b NonBlocker) Block() {} type SleepBlocker time.Duration func (s SleepBlocker) Block() { time.Sleep(time.Duration(s)) } func (s SleepBlocker) Sleep() { s.Block() } type StaticBlocker interface { Sleep() } type Empty interface{} type FooByte int func (f FooByte) Byte() byte { return byte(f) } type Byter interface { Byte() uint8 } // Make sure that named types inside functions do not alias with any other named // functions. type named int func named1() any { return named(0) } func named2() any { type named int return named(0) } func named3() any { type named int return named(0) } func namedptr1() interface{} { type Test int return (*Test)(nil) } func namedptr2() interface{} { type Test byte return (*Test)(nil) } func ptrptrswitch() { identify(0) identify(new(int)) identify(new(*int)) } func identify(itf any) { switch itf.(type) { case int: println("type is int") case *int: println("type is *int") case **int: println("type is **int") default: println("other type??") } }