博客 记录生活,记录工作。

Go类型断言

2017-12-08
go

Golang中类型断言主要体现两种方式:Type assertionsType switches,下面我们分别进行分析。

Type assertions

对于==接口类型==的表达式x和类型T,Go的类型断言可表示如下,

x.(T)

类型断言将断言变量x不为nil并且x中值的类型是T。如果T不是接口类型,x.(T)断言x的动态类型与T相同;如果T是接口类型,x.(T)断言x的动态类型实现了接口T

如果断言成立,表达式的值是存储在x中的值,并且其类型为T;如果断言失败,则会发生运行时panic。

var x interface{} = 7   //x动态类型是int,值为7
i := x.(int)            //i的类型是int,值为7
j := x.(float64)        //panic

类型断言在赋值或初始化的时候,会产生一个额外的bool值,即如果断言成功ok为true。否则是false,并且v的值是类型T的零值,此时不会发生panic。

v, ok := x.(T)

即,如下示例

    var value interface{}
    value = "string"
    if str, ok := value.(string); ok {
        fmt.Printf("%T  %v", str, str)
    }
    if i, ok := value.(int); ok {
        fmt.Printf("%T  %v", i, i)
    }

Type switches

Type switches比较的是变量的类型而不是值 ,使用保留字type作为断言的参数。即,

switch newval := value.(type) {
case int :
    //do something
default :
    //do something
}

需要注意value是interface,变量newval类型是转换后的类型。下面我们看一下具体的例子,

package main

import "fmt"

type mystruct struct {
    string
}

func main() {
    //v := 3.12     //case float
    //var v mystruct    //case mystruct
    var v interface{}   //case nil

    checkType(v)

    fmt.Printf("\n%v  %T", v, v)
}

func checkType(v interface{}) {
    //switch v.(type) {
    switch t := v.(type) {
    case *int:
        *t = 10 //change value
        fmt.Println("\rIn *int")
    case float64:
        t = 20 //not change value
        fmt.Println("\rIn float64")
    case mystruct:
        fmt.Println("\rIn mystruct")
    case nil:
        fmt.Println("\rIn nil")
    default:
        fmt.Println("\rIn default")
    }
}

总结

使用x.(typename)时需要注意以下问题,

  1. x必须是interface{}
  2. typename为具体类型的时候,必须进行comma, ok判断,否则容易产生panic
  3. typenametype时,表达式只能用在switch中,另外对x的数据做操作的时候,需新定义变量t, 即t := v.(type)

相关博文

下一篇 stress介绍

评论