本文发布于Cylon的收藏册,转载请著名原文链接~


类型断言

类型断言 type assertion 并不是真正的将 interface 类型转换为另一种确定的类型,只是提供了对 interface 类型的值的访问,通常情况下,这是常见的需求

类型断言通过 语法 x.(T) ,这将会确定 x 变量中存储的值是否属于 T 类型,通常场景有两种:

  • 如果 T 不是 interface 类型,而是一个具体的类型,那么这次断言将断言 x 的 动态类型是否与 T 相同
  • 如果 T 是 interface 类型,这次断言 x 的动态类型是否实现了 T
var x interface{} = "foo"

var s string = x.(string)
fmt.Println(s)     // "foo"

s, ok := x.(string)
fmt.Println(s, ok) // "foo true"

n, ok := x.(int)
fmt.Println(n, ok) // "0 false"

n = x.(int)        // ILLEGAL

Note:在断言时,x 的类型必须为 interface{}

那么怎么理解 T=interfaceT != interface 这两句话呢

  • T != interface 则是一个正常的断言,即 x (interface) 是否等于 T (really type),这里 x 必须为 interface,T 则可以为任意类型而不是变量
  • T=interface 时 不能说是一个断言,而是一个对 interface 的断言,此时 x 必须为 interface,T 也必须为 interface

如下面代码所示:

type s interface {}

// 一个interface类型的变量a
var a interface{}
a = a
a = 1

// 一个int 类型的变量b
var b = 20
b = b

x, ok := a.(s) // 1 true 因为a实现了interface
x, ok := b.(s) //  false b 不是interface不能断言
x, ok := a.(int) // 1 true 因为a的值为int
x := a.(string) // 当一个返回参数时将触发panic

类型转换

类型转换 type switch 是指类型断言的应用场景,是通过对一个interface类型的变量进行多次断言,以匹配到真实的数据类型

var x interface{} = "foo"

switch v := x.(type) {
case nil:
	fmt.Println("x is nil")            // here v has type interface{}
case int: 
	fmt.Println("x is", v)             // here v has type int
case bool, string:
	fmt.Println("x is bool or string") // here v has type interface{}
default:
	fmt.Println("type unknown")        // here v has type interface{}
}

本文发布于Cylon的收藏册,转载请著名原文链接~

链接:https://www.oomkill.com/2023/01/go-type-assertion/

版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」 许可协议进行许可。