
This is the kind that is used in Go (actually CGo) for exporting functions. I think it's best to use //export instead of our custom //go:export pragma, for consistency (they are equivalent in TinyGo). Therefore I've updated all instances to the standard format (except for two that are updated in https://github.com/tinygo-org/tinygo/pull/1024). No smoke tests changed (when comparing the output hash), except for some wasm tests that include DWARF debug info and tend to be flaky anyway.
110 строки
1,8 КиБ
Go
110 строки
1,8 КиБ
Go
package main
|
|
|
|
type Thing struct {
|
|
name string
|
|
}
|
|
|
|
type ThingOption func(*Thing)
|
|
|
|
func WithName(name string) ThingOption {
|
|
return func(t *Thing) {
|
|
t.name = name
|
|
}
|
|
}
|
|
|
|
func NewThing(opts ...ThingOption) *Thing {
|
|
t := &Thing{}
|
|
for _, opt := range opts {
|
|
opt(t)
|
|
}
|
|
return t
|
|
}
|
|
|
|
func (t Thing) String() string {
|
|
return t.name
|
|
}
|
|
|
|
func (t Thing) Print(arg string) {
|
|
println("Thing.Print:", t.name, "arg:", arg)
|
|
}
|
|
|
|
type Printer interface {
|
|
Print(string)
|
|
}
|
|
|
|
func main() {
|
|
thing := &Thing{"foo"}
|
|
|
|
// function pointers
|
|
runFunc(hello, 5) // must be indirect to avoid obvious inlining
|
|
|
|
// deferred functions
|
|
testDefer()
|
|
|
|
// defers in loop
|
|
testDeferLoop()
|
|
|
|
// Take a bound method and use it as a function pointer.
|
|
// This function pointer needs a context pointer.
|
|
testBound(thing.String)
|
|
|
|
// closures
|
|
func() {
|
|
println("thing inside closure:", thing.String())
|
|
}()
|
|
runFunc(func(i int) {
|
|
println("inside fp closure:", thing.String(), i)
|
|
}, 3)
|
|
|
|
// functional arguments
|
|
thingFunctionalArgs1 := NewThing()
|
|
thingFunctionalArgs1.Print("functional args 1")
|
|
thingFunctionalArgs2 := NewThing(WithName("named thing"))
|
|
thingFunctionalArgs2.Print("functional args 2")
|
|
}
|
|
|
|
func runFunc(f func(int), arg int) {
|
|
f(arg)
|
|
}
|
|
|
|
func hello(n int) {
|
|
println("hello from function pointer:", n)
|
|
}
|
|
|
|
func testDefer() {
|
|
defer exportedDefer()
|
|
|
|
i := 1
|
|
defer deferred("...run as defer", i)
|
|
i++
|
|
defer func() {
|
|
println("...run closure deferred:", i)
|
|
}()
|
|
i++
|
|
defer deferred("...run as defer", i)
|
|
i++
|
|
|
|
var t Printer = &Thing{"foo"}
|
|
defer t.Print("bar")
|
|
|
|
println("deferring...")
|
|
}
|
|
|
|
func testDeferLoop() {
|
|
for j := 0; j < 4; j++ {
|
|
defer deferred("loop", j)
|
|
}
|
|
}
|
|
|
|
func deferred(msg string, i int) {
|
|
println(msg, i)
|
|
}
|
|
|
|
//export __exportedDefer
|
|
func exportedDefer() {
|
|
println("...exported defer")
|
|
}
|
|
|
|
func testBound(f func() string) {
|
|
println("bound method:", f())
|
|
}
|