这是我参与「第三届青训营 -后端场」笔记创作活动的第8篇笔记。
一、封装
一、认识Interface与断言
1、所有程序都实现了interface{} 的接口(类似于Java中的Object)
- 所有的类型如string,int,int64甚至是自定义的struct类型都就此拥有了interface{}的接口,这种做法和java中的Object类型比较类似。
那么在一个数据通过func funcName(interface{})的方式传进来的时候,也就意味着这个参数被自动的转为interface{}的类型。
2、Golang的语言中提供了断言的功能。
二、直接断言与判断断言(类型转换)
2.1、错误示范与断言演示
错误示例
比如说我们想要将一个函数中的参数转为string返回,可以尝试如下:
func funcName(a interface{}) string {
return string(a)
}
不过这个会在编译期间就出现报错
直接断言与判断断言
下面我们来使用直接断言与判断断言两种方式来进行转换:
1、直接断言
package main
import "fmt"
//1、直接断言方式
func funcName1(a interface{}) string {
return a.(string) //直接断言,若是转型失败,则会抛出异常程序结束
}
func main() {
//传入字符串:这个肯定能转型成功
fmt.Println(funcName1("changlu"))
//传入数字:这个类型不是string,那么就会
fmt.Println(funcName1(123))
}
2、判断断言
通过使用两个值来接收,接着来进行判断是否断言成功
package main
import "fmt"
//2、判断断言
func funcName(a interface{}) string {
value, ok := a.(string)
if (!ok) {
//若是转型失败
fmt.Println("转型失败")
}
return value
}
func main() {
//传入字符串:这个肯定能转型成功
fmt.Println(funcName("changlu"))
//传入数字:这个类型不是string,那么就会
fmt.Println(funcName(123))
}
2.2、类实现多个接口来使用断言转换(实际场景)
案例:将子类实例向上转型接口。(其中也有多态的影子)
package main
import "fmt"
type reader interface {
read()
}
type writer interface {
write()
}
//实现类,实现了两个接口
type MyFile struct {
}
func (this *MyFile) read() {
fmt.Println("read ...")
}
func (this *MyFile) write() {
fmt.Println("write ...")
}
func main() {
file := &MyFile{}
//父类接口引用指向子类实例
var r reader
r = file
r.read()
//通过断言转型为子类实例的另一个writer接口,此时就能够调用write()方法
w := r.(writer)
w.write()
}
三、优雅转型方式:switch(及if)
package main
import "fmt"
//2、判断断言
func funcName(a interface{}) interface{} {
//获取类型a.(type)必须写在switch中
switch t := a.(type) {
case string:
fmt.Printf("类型:%T ", t) //打印类型
return a.(string)
case int:
fmt.Printf("类型:%T ", t)
return a.(int)
default:
fmt.Println("暂无类型转换")
return nil
}
}
func main() {
//传入字符串:这个肯定能转型成功
fmt.Println(funcName("changlu"))
//传入数字:这个类型不是string,那么就会
fmt.Println(funcName(123))
}
其他方式就是if了,示例如下,有需要可以去进行仿写
func sqlQuote(x interface{}) string {
if x == nil {
return "NULL"
} else if _, ok := x.(int); ok {
return fmt.Sprintf("%d", x)
} else if _, ok := x.(uint); ok {
return fmt.Sprintf("%d", x)
} else if b, ok := x.(bool); ok {
if b {
return "TRUE"
}
return "FALSE"
} else if s, ok := x.(string); ok {
return sqlQuoteString(s) // (not shown)
} else {
panic(fmt.Sprintf("unexpected type %T: %v", x, x))
}
}
参考文章
[1] 8、interface与类型断言