反射 reflect
type CfgSt struct{
Match *int64 `ini:"match"`
Desc string `ini:"desc"`
Level *int64 `ini:"level"`
}
如果结构体不是指针:
typ := reflect.TypeOf(c)
val := reflect.ValueOf(c)
如果结构体是指针:
typ := reflect.TypeOf(c).Elem()
val := reflect.ValueOf(c).Elem()
结构体成员数:
val.NumField()
结构体成员名:
val.Type().Field(idx).Name
结构体成员tag名:
typ.Field(idx).Tag.Get("ini")
成员值:
val.Field(idx).Interface()
值得类型断言
switch v := val.Field(idx).Interface().(type) {
case *int64:
if val.Field(idx).IsNil() {
continue
}
log.Println(*v)
case string:
log.Println(v)
}
接口 interface
- 如果对象实现了接口的所有方法,那么可以把对象的实例赋值给该接口;但是接口不能调用对象中接口没有定义的方法。
- 可以在编译时检查接口是否被实现,利用下面两种中的一种即可
- var _ face = (*rabbit)(nil) // 推荐用这种方式
- var _ face = new(rabbit)
- 传值的方法会默认实现传引用的方法,反之不成立
- 比如 func (r rabbit) Sayhi() 默认实现 func (r *rabbit) Sayhi(),但是反之不成立
- 不能直接对内嵌类型添加方法
package main
import (
"log"
)
type face interface {
Sayhi()
Bye()
}
type rabbit struct {}
func (r rabbit) Sayhi() {
log.Println("rabbit say hi")
}
func (r rabbit) Do() {
log.Println("rabbit do something")
}
func (r rabbit) Bye() {
log.Println("rabbit say bye")
}
type ty int64
func (r ty) Sayhi() {
log.Println("ty say hi")
}
func (r ty) Bye() {
log.Println("ty say bye")
}
func (r ty) Do() {
log.Println("ty do something")
}
// 类似于assert断言,在编译时候检查是否实现了接口
// 类型断言是在运行时动态检查
var _ face = (*rabbit)(nil)
var _ face = new(rabbit) // 不推荐,因为为对象会分配空间
var _ face = (*ty)(nil)
func main() {
var i face
i = rabbit{}
i.Sayhi()
//i.Do()
i.Bye()
var a ty // 不可少不能直接用 i = ty{}
i = a
i.Sayhi()
i.Bye()
}
类型断言
- 指定类型typename断言
if v, ok := i.(typename);ok {
log.Println(v)
} else {
log.Println("invalid")
}
- 不指定类型断言
switch i.(type) {
case int:
...
case int64:
...
...
}
判断map是否包含成员
类似于类型断言
m := make(map[string]int, 0)
if v, ok := m["asd"];ok {
log.Println(v)
} else {
log.Println("invalid")
}
流控语句
- fallthrough
go 中switch每个分支默认执行完毕break,这与c语言不一样。
可以通过添加 fallthrough来实现类似c的效果
switch {
case false:
log.Println(0)
fallthrough
case true:
log.Println(1)
fallthrough
case false:
log.Println(2)
fallthrough
default:
log.Println("default cannot use fallthrough")
//fallthrough
}
- break
go 中break可以指定退出的循环,默认只退出最内层循环
mark:
for {
for idx := 0; idx < 10; idx++ {
log.Println("for ", idx)
if idx == 5 {
break mark
}
}
}