golangタイプ断言

10663 ワード

defs:
形はres,ok:=x.(T)の式がタイプ断言であり、xはインタフェース(空のインタフェースでもよい)でなければならない.Tはインタフェースまたは特定のタイプであってもよい.okは断言が成功したかどうかを示し、成功すればresの値はxの値であり、タイプはxのタイプでなければpanicではない.
case 1:x is nil,panic
    var x interface{} = nil
    fmt.Print(x.(int))

Case 2:T is type,Tが元のタイプと一致すると,成功と断言し,そうでなければ失敗する.
    var x interface{} = 1
    fmt.Println("x      :", reflect.TypeOf(x))

    if res, ok := x.(int); ok {
        fmt.Println("    ,res    ", res)
    }

    if res, ok := x.(string); !ok {
        fmt.Println("    ,res        (   )", res)
    }


  example 2:
    var w io.Writer = os.Stdout // os.Stdout   *os.File   ,    io.Writer
    f := w.(*os.File)           // success: f == os.Stdout
    c := w.(*bytes.Buffer)      // panic: interface holds *os.File, not *bytes.Buffer


Case 3:T is interface,xがTインタフェース example 1を実現したか否かを判断する.
package main

import (
    "fmt"
    "reflect"
)

type Runner interface {
    run()
}
type Flyer interface {
    fly()
}
type RunnerFlyer interface {
    Runner
    Flyer
}

type Person struct {}
type Chicken struct {}

func (*Chicken) run() {}
func (*Chicken) fly() {}
func (*Person) run() {}

func main() {
    var x Runner = &Chicken{}
    res, ok := x.(Flyer)
    fmt.Printf("  :%v,res    :%v:
"
, ok, reflect.TypeOf(res)) // :true,res :*main.Chicken: x = &Person{} res, ok = x.(Flyer) fmt.Printf(" :%v,res :%v:", ok, reflect.TypeOf(res)) // :false,res : var rf RunnerFlyer = &Chicken{} v, ok := rf.(Flyer) v.fly() //ok v.run() //can't use run }

  example 2:
    var w io.Writer
    w = os.Stdout
    rw := w.(io.ReadWriter) // success: *os.File has both Read and Write
    w = new(strings.Builder)
    rw := w.(io.ReadWriter) // panic: *strings.Builder has no Read method