GO语言的错误与反射 | 青训营;

58 阅读3分钟

错误处理

go语言中跟其他语言不太一样,go语言中没有异常,只有错误,它将错误当成一种值来进行处理。

Error接口

go语言中有一个error接口来表示错误类型。并且error中只有Error一个方法。

type error interface{ 
Error() string 
} 
//当一个函数或者方法需要返回错误时,我们通常把错误作为最后一个返回。 
func Open(name string) (*File, error) { 
return OpenFile(name, O_RDONLY, 0)
} 
//error是一个接口类型,因此它的默认零值是nil。我们也通常把错误于nil进行判断。
func main() { 
file, err := os.Open(test.go") 
    if err != nil {
        fmt.Println("open failed, err:", err) 
        return 
        } 
    }

自定义错误

自定义错误是指实现了error接口的类型,可以用来表示更复杂的错误信息和功能。error接口只有一个方法,Error() string,用来返回错误的描述。你可以使用errors包或fmt包提供的函数来创建简单的错误,也可以自己定义一个结构体或者类型来实现error接口,从而创建自定义错误。自定义错误可以包含更多的上下文信息,也可以支持错误的链式调用和断言。

func New(test string) error
func cal(n int) error { 
if n < 10 { err := errors.New("num is to small")
return err
} 
return nil 
} 
func main(){
n := 5 fmt.Println(cal(n)) //num is to small 
   }

fmt.Errorf

当我们需要对格式化的错误描述信息时,我们可以使用fmt.Errorf

fmt.Error
f("err: %v\n", err)
//为了保证函数调用的错误链不丢失,我们可以使用%w
fmt.Errorf("err: %w\n", err)

反射

反射是一种在运行时动态操作对象的能力,它可以让你获取对象的类型和值,以及修改、调用或创建对象。Go语言的反射主要依赖于reflect包,它提供了两个重要的函数:reflect.TypeOf和reflect.ValueOf,分别用来获取对象的类型和值。反射还可以用来实现泛型、元编程、序列化等功能。

TypeOf

go语言中,我们可以使用内嵌的reflect.TypeOf()来获得任意值的类型对象,程序可以通过类型对象来访问任意值的类型信息。

func reflectType(x interface{}) {
v := reflect.TypeOf(x) fmt.Printf("%v\n", v)
} 
func main() { 
var a float64 = 3.14 
reflectType(a) //float64 
var b int = 100
reflectType(b) //int
}

反射中关于类型划分为两种:类型(Type)种类(Kind)。因为在Go语言中我们可以使用type关键字构造很多自定义类型,而种类(Kind)就是指底层的类型,但是在反射中,当我们需要区分指针、结构体等类型时,就会用到种类(Kind)。 举个例子,我们定义了两个指针类型和两个结构体类型,通过反射查看它们的类型和种类。

type myInt int64 
func reflectType(x interface{}) {
t := reflect.TypeOf(x) 
fmt.Printf("type:%v kind:%v\n", t.Name(), t.Kind())
} 
func main() { 
var a *float32 // 指针
var b myInt // 自定义类型
var c rune // 类型别名
reflectType(a) // type: kind:ptr
reflectType(b) // type:myInt kind:int64 
reflectType(c) // type:int32 kind:int32 
type person struct { name string age int }
type book struct{ title string } 
var d = person{ name: "张三", age: 18, }
var e = book{title: "《跟博笙一起学习Go》"} 
reflectType(d) // type:person kind:struct 
reflectType(e) // type:book kind:struct 
}

ValueOf

go语言中的reflect.ValueOf()返回的是reflect.Value类型,包括原始值的值信息。reflect.Value与原始值之间可以相互转换。

我们可以通过反射获取值。

func reflectValue(x interface{}) {
v := reflect.ValueOf(x) k := v.Kind() switch k { 
case reflect.Int64: // v.Int()从反射中获取整型的原始值,然后通过int64()强制类型转换 
fmt.Printf("type is int64, value is %d\n", int64(v.Int())) case reflect.Float32: // v.Float()从反射中获取浮点型的原始值,然后通过float32()强制类型转换
fmt.Printf("type is float32, value is %f\n", float32(v.Float())) case reflect.Float64: // v.Float()从反射中获取浮点型的原始值,然后通过float64()强制类型转换
fmt.Printf("type is float64, value is %f\n", float64(v.Float()))
} 
} 
func main() { var a float32 = 3.14 var b int64 = 100 reflectValue(a) // type is float32, value is 3.140000 reflectValue(b) // type is int64, value is 100 // 将int类型的原始值转换为reflect.Value类型 c := reflect.ValueOf(10) fmt.Printf("type c :%T\n", c) // type c :reflect.Value
}

我们还可以通过反射设置变量的值。