第三十七:类型断言

Go 复制代码
package main

import (
	"fmt"
	"go/types"
)

func doSomething(i interface{}) {
	switch v := i.(type) {
	case int:
		fmt.Println("Integer:", v)
	case string:
		fmt.Println("String:", v)
	default:
		fmt.Println("Unknown type")
	}
}

// 区分字符串、数组、切片

func aa(i interface{}) {
	switch v := i.(type) {
	case string:
		fmt.Println("i is a string:", v)
	case int:
		fmt.Println("i is an int:", v)
	case types.Slice:
		fmt.Println("i is a slice:", v)
	case types.Array:
		fmt.Println("i is an array:", v)
	case []string:
		fmt.Println("i is a slice of strings:", v)
	case []int:
		fmt.Println("i is a slice of int:", v)
	case []interface{}:
		fmt.Println("i is a slice of interface{}:", v)
	default:
		fmt.Println("i is of a different type")
	}
}

func main() {

	aa("hello")
	aa(123)
	aa([]int{1, 2, 3})
	aa([]string{"aaa", "bbb", "ccc"})
	aa([3]int{4, 5, 6})
	aa([]interface{}{1, "a", true})

}

判断是否为切片(不区分元素类型)

Go 复制代码
func isSlice(value interface{}) bool {
    switch value.(type) {
    case []interface{}, []string, []int, []float64, []bool:
        return true
    default:
        // 使用反射判断任意切片类型
        return reflect.TypeOf(value).Kind() == reflect.Slice
    }
}

2. 使用反射(reflect包)

Go 复制代码
import "reflect"

func checkTypeReflect(value interface{}) {
    v := reflect.ValueOf(value)
    
    switch v.Kind() {
    case reflect.String:
        fmt.Println("字符串类型")
    case reflect.Slice:
        fmt.Println("切片类型")
        // 进一步判断切片元素类型
        if v.Type().Elem().Kind() == reflect.String {
            fmt.Println("元素类型是 string")
        } else if v.Type().Elem().Kind() == reflect.Interface {
            fmt.Println("元素类型是 interface{}")
        }
    case reflect.Array:
        fmt.Println("数组类型")
    default:
        fmt.Printf("类型: %v\n", v.Kind())
    }
}

3. 判断是否为数组(不是切片)

Go 复制代码
func isArray(value interface{}) bool {
    t := reflect.TypeOf(value)
    return t.Kind() == reflect.Array
}

func isSlice(value interface{}) bool {
    t := reflect.TypeOf(value)
    return t.Kind() == reflect.Slice
}

func isString(value interface{}) bool {
    t := reflect.TypeOf(value)
    return t.Kind() == reflect.String
}

4. 实用示例函数

Go 复制代码
import (
    "fmt"
    "reflect"
)

func GetTypeInfo(value interface{}) (string, string) {
    v := reflect.ValueOf(value)
    kind := v.Kind()
    
    var typeName string
    var elementType string
    
    switch kind {
    case reflect.String:
        typeName = "string"
    case reflect.Slice:
        typeName = "slice"
        // 获取元素类型
        elemType := v.Type().Elem()
        elementType = elemType.String()
    case reflect.Array:
        typeName = "array"
        elemType := v.Type().Elem()
        elementType = elemType.String()
    default:
        typeName = kind.String()
    }
    
    return typeName, elementType
}

// 使用示例
func main() {
    str := "hello"
    strSlice := []string{"a", "b"}
    intSlice := []int{1, 2}
    arr := [3]int{1, 2, 3}
    
    fmt.Println(GetTypeInfo(str))       // string, 
    fmt.Println(GetTypeInfo(strSlice))  // slice, string
    fmt.Println(GetTypeInfo(intSlice))  // slice, int
    fmt.Println(GetTypeInfo(arr))       // array, int
}

5. 判断是否为字符串切片(特定类型)

Go 复制代码
func IsStringSlice(value interface{}) bool {
    switch v := value.(type) {
    case []string:
        return true
    default:
        // 使用反射检查
        rv := reflect.ValueOf(value)
        if rv.Kind() != reflect.Slice {
            return false
        }
        return rv.Type().Elem().Kind() == reflect.String
    }
}

func IsSliceOfType(value interface{}, elemKind reflect.Kind) bool {
    rv := reflect.ValueOf(value)
    if rv.Kind() != reflect.Slice {
        return false
    }
    return rv.Type().Elem().Kind() == elemKind
}

主要区别:

  1. 字符串string 类型

  2. 数组 :固定长度,如 [3]int

  3. 切片 :可变长度,如 []int[]string

方法1:使用反射(reflect)

Go 复制代码
package main

import (
	"fmt"
	"reflect"
)

func main() {
	var s []int = []int{1, 2, 3}
	fmt.Println(isSlice(s)) // 输出:true

	var n int = 10
	fmt.Println(isSlice(n)) // 输出:false
}

func isSlice(x interface{}) bool {
	return reflect.TypeOf(x).Kind() == reflect.Slice
}

方法2:使用类型断言

Go 复制代码
package main

import (
	"fmt"
)

func main() {
	var s []int = []int{1, 2, 3}
	fmt.Println(isSlice(s)) // 输出:true,但这种方式主要用于已知具体类型的情况,不是通用检查是否为切片的最佳方法。
}

// 注意:下面的方法实际上并不适用于通用检查是否为切片,因为你需要知道具体的切片类型。
// 正确的做法应该是使用反射或直接比较类型。
func isSlice(x interface{}) bool {
	_, ok := x.([]int) // 这里需要明确知道切片的元素类型。这不是通用方法。
	return ok
}

正确的通用方法:使用反射检查任意切片类型

Go 复制代码
package main

import (
	"fmt"
	"reflect"
)

func main() {
	var s []int = []int{1, 2, 3}
	fmt.Println(isAnySlice(s)) // 输出:true
	var s2 []string = []string{"a", "b", "c"}
	fmt.Println(isAnySlice(s2)) // 输出:true
}

func isAnySlice(x interface{}) bool {
	return reflect.TypeOf(x).Kind() == reflect.Slice
}

用reflect包来判断变量是数组还是切片

Go 复制代码
    arr := [5]int{1, 2, 3, 4, 5}
	slice := []int{1, 2, 3, 4, 5}
 
	// 判断数据类型
	arrType := reflect.TypeOf(arr)
	sliceType := reflect.TypeOf(slice)
 
	// 输出结果
	fmt.Println("arrType:", arrType)   
          //结果为 [5]int
	fmt.Println("sliceType:", sliceType)
           //结果为  []int
 
    fmt.Println(arrType.Kind())
           //结果为 array
	fmt.Println(sliceType.Kind())
           //结果为slice
}
相关推荐
编织幻境的妖2 小时前
Python读写CSV与JSON文件方法
开发语言·python·json
九年义务漏网鲨鱼2 小时前
【大模型微调】QLoRA微调原理及实战
深度学习·算法·大模型·智能体
2401_841495642 小时前
【LeetCode刷题】合并区间
数据结构·python·算法·leetcode·合并·遍历·排序
weixin_307779132 小时前
Jenkins jQuery3 API 插件详解:赋能插件前端开发的利器
运维·开发语言·前端·jenkins·jquery
世转神风-2 小时前
QEventLoop-qt阻塞异步操作
开发语言·qt
Hard but lovely2 小时前
C++ 11--》初始化
开发语言·c++
LiamTuc2 小时前
Java 接口定义变量
java·开发语言
xu_yule2 小时前
数据结构(14)二叉树的模拟实现和便利代码
数据结构·算法
昇腾CANN3 小时前
自定义算子开发系列:TilingKey模板化编程介绍
c++·mfc