The content on this page is written in Chinese, and then traslated into English by machine. More accurate traslations are welcome at: https://github.com/wa-lang/man/tree/master/en

Ending's law: "Any application that can be compiled to WebAssembly, will be compiled to WebAssembly eventually."

7.3. Summary of type assertions

Section 7.1 introduces how to obtain the specific value contained in an interface value of type interface{} through type assertion. This usage still holds for non-null interface values, for example:

// 版权 @2023 凹语言 作者。保留所有权利。

type Printer interface {
    Print()
}

type T1 struct {
    i: i32
}

func T1.Print { println("This is T1, this.i:", this.i) }

type T2 struct {
    s: string
}

func T2.Print { println("This is T2, this.s:", this.s) }

func doConcrete(p: Printer) {
    switch v := p.(type) {
    case *T1:
        v.Print()

    case *T2:
        v.Print()
    }
}

func main {
    v1 := T1{i: 42}
    doConcrete(&v1) // This is T1, this.i: 42

    v2 := T2{s: "hello"}
    doConcrete(&v2) // This is T2, this.s: hello
}

Note that v.Print() in function doConcrete is a direct call, not an interface call, because in the case *T1 branch, the type of v is *T1. In addition, non-null interface values can also perform concrete type assertions in the form of v, ok = iface.(Type), which is consistent with the application method of null interface values in Section 7.1.

In fact, the usage of type assertions goes beyond this. In some cases, a concrete type *T may satisfy multiple interfaces I1 and I2 at the same time. Then when the interface value of an I1 contains concrete value type of *T, you can directly obtain an interface value of type I2 through type assertion on the interface value, for example:

// 版权 @2023 凹语言 作者。保留所有权利。

type I1 interface {
    f1()
}

type I2 interface {
    f2()
}

type T struct {
    i: i32
}

func T.f1 { println("T.f1(), T.i:", this.i) }

func T.f2 { println("T.f2(), T.i:", this.i) }

func main {
    v1 := T{i: 42}

    i1: I1 = &v1
    i1.f1() // T.f1(), T.i: 42

    i2, ok := i1.(I2) // 断言为另一个接口
    if ok {
        i2.f2() // T.f2(), T.i: 42
    }
}

This usage is generally seen in getting a non-null interface from an interface{} value.

In addition to type assertions of the form v, ok = iface.(Type), there is another pattern of type assertions:

    v = iface.(Type)

This mode omits the ok flag indicating whether the operation was successful and only returns the value of the asserted type. If a type assertion fails, a runtime exception will be triggered, and it is recommended to only use this pattern if you are absolutely certain that the assertion will not fail.