错误处理
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
}
我们还可以通过反射设置变量的值。