一,反射
1.Go反射
- interface
interface(接口)是golang最重要的特性之一,Interface类型可以定义一组方法,但是这些不需要实现。并且interface不能包含任何变量。
- interface是方法的集合
- interface是一种类型,并且是指针类型
- interface的更重要的作用在于多态实现
- 接口的使用不仅仅针对结构体,自定义类型、变量等等都可以实现接口。
- 如果一个接口没有任何方法,我们称为空接口,由于空接口没有方法,所以任何类型都实现了空接口。
- 要实现一个接口,必须实现该接口里面的所有方法。
- 反射就是用来检测存储在接口变量内部(值value;类型concrete type) pair对的一种机制。反射一般配合接口一起使用,反射使go语言更灵活。但是反射的效率比较慢。
用例: 反射其中一个用法是在数据库映射时使用,将数据映射到结构体中。
/*
通过tag将map中的数据映射到结构体中
*/
func DataToStructByTag(data map[string]interface{}, obj interface{}, tagName string) (err error) {
valueObj := reflect.ValueOf(obj).Elem()
for i := 0; i < valueObj.NumField(); i++ {
value := data[valueObj.Type().Field(i).Tag.Get(tagName)]
valueR := reflect.ValueOf(value)
if valueR.Type().Name() != valueObj.Type().Field(i).Type.Name() {
err = fmt.Errorf("type %s cant convert to type %s.", valueR.Type().Name(), valueObj.Type().Field(i).Type.Name())
return
}
if valueObj.FieldByName(valueObj.Type().Field(i).Name).CanSet() {
valueObj.FieldByName(valueObj.Type().Field(i).Name).Set(valueR)
}
}
return
}
2.Python 反射
- hasattr,getattr,setattr,delattr
python里面的反射是通过以上4种函数实现。hasattr用来判断某个对象是否包含某个属性或方法。getattr用来获得某个属性或方法。setattr是设置对象的属性或方法。delattr删除对象的属性。
# 通过实例类对象来操作sql语句!!就是所谓的ORM
class ModelMetaclass(type):
def __new__(cls, name, bases, attrs):
mappings = dict()
# 判断是否需要保存
for k, v in attrs.items():
# 判断是否是指定的StringField或者IntegerField的实例对象
if isinstance(v, tuple):
print('Found mapping: %s ==> %s' % (k, v))
mappings[k] = v
# 删除这些已经在字典中存储的属性
for k in mappings.keys():
attrs.pop(k)
# 将之前的uid/name/email/password以及对应的对象引用,类名字
attrs['__mappings__'] = mappings # 保存属性和列的映射关系
attrs['__table__'] = name # 假设表名和类名一致
return type.__new__(cls, name, bases, attrs)
class User(metaclass=ModelMetaclass):
uid = ("uid", "int unsigned")
name = ("username", "varchar(30)")
price = ("price", "double")
email = ("email", "varchar(30)")
password = ("password", "varchar(30)")
# 当指定元类之后,以上的类属性将不在类中,而是在__mappings__属性指定的字典中存储
# 以上User类中有
# __mappings__ = {
# "uid" : ("uid", "int unsigned"),
# "name" : ("username", "varchar(30)"),
# "email" : ("email", "varchar(30)"),
# "password" : ("password", "varchar(30)"),
# }
# __table__ = "User"
def __init__(self, **kwargs):
for name, value in kwargs.items():
setattr(self, name, value)
# self.name = value
def save(self):
fields = []
args = []
for k, v in self.__mappings__.items():
fields.append(v[0])
args.append(getattr(self, k, None))
# sql = 'inset into %s (%s) values (%s)' % (self.__table__,','.join(fields), ','.join([str(i) for i in args]))
args_temp = list()
for temp in args:
# 判断如果是数字类型
if isinstance(temp, (int, float)):
args_temp.append(str(temp))
elif isinstance(temp, str):
args_temp.append("""'%s'""" % temp)
sql = 'insert into %s (%s) value (%s)' % (self.__table__, ','.join(fields), ','.join(args_temp))
print("SQL: %s" % sql)
u = User(uid=12345, name='Michael', email='test@orm.org', password='my_pwd', price=1.2)
print(u.__dict__)
u.save()
二,垃圾回收
1. Go的垃圾回收官方形容为 非分代 非紧缩 写屏障 三色并发标记清理算法。
非分代
不像Java那样分为年轻代和年老代,自然也没有minor gc和maj o gc的区别。
非紧缩
在垃圾回收之后不会进行内存整理以清除内存碎片。
写屏障
在并发标记的过程中,如果应用程序(mutator)修改了对象图,就可能出现标记遗漏的可能,写屏障就是为了处理标记遗漏的问题。
三色
将GC中的对象按照搜索的情况分成三种:
- 黑色: 对象在这次GC中已标记,且这个对象包含的子对象也已标记
- 灰色: 对象在这次GC中已标记, 但这个对象包含的子对象未标记
- 白色: 对象在这次GC中未标记
并发
可以和应用程序(mutator)在一定程度上并发执行。
标记清理
GC算法分为两个大步骤:标记阶段找出要回收的对象,清理阶段则回收未被标记的对象(要被回收的对象)。
Go 历史版本垃圾回收暂停时间
2. python垃圾回收
引用计数
Python垃圾回收主要以引用计数为主,分代回收为辅。引用计数法的原理是每个对象维护一个ob_ref,用来记录当前对象被引用的次数,也就是来追踪到底有多少引用指向了这个对象,当发生以下四种情况的时候,该对象的引用计数+1,当引用计数为0时会被python虚拟机回收。
优点
- 高效
- 运行期没有停顿 可以类比一下Ruby的垃圾回收机制,也就是 实时性:一旦没有引用,内存就直接释放了。不用像其他机制等到特定时机。实时性还带来一个好处:处理回收内存的时间分摊到了平时。
- 对象有确定的生命周期
- 易于实现
缺点
- 维护引用计数消耗资源,维护引用计数的次数和引用赋值成正比,而不像mark and sweep等基本与回收的内存数量有关。
- 无法解决循环引用的问题。A和B相互引用而再没有外部引用A与B中的任何一个,它们的引用计数都为1,但显然应该被回收。
手动回收
import gc
gc.collect()
三,标签
- 跳出外层循环使用break label :
fmt.Println("in")
Loop:
for{
fmt.Println("outer")
for{
fmt.Println("inner")
break Loop
}
}
fmt.Println("out")
- python里面没有标签,当要实现跳出多重循环时可以借助异常:
class LoopBreakException(Exception):
pass
def loop_test():
try:
for i in range(1, 20):
for j in range(0,100):
if j % i == 13:
print(i, j)
raise LoopBreakException()
except LoopBreakException:
pass
if __name__ == '__main__':
loop_test()
- goto 语句可以让程序切换到某个被 Label 标记的地方继续执行。
i := 0
Start:
if i<10{
i+=1
goto Start
}else{
goto End
}
End:
四,多态
多态的字面意思是多种状态,在面向对象的语言中,接口的多种不同的实现方式即为多态。多态性是允许你将父对象设置成为一个或更多的他的子对象相等的技术,赋值之后,父对象就可以根据当前赋值给它的子对象的特性以不同的方式运作。简单的说,就是一句话:允许将子类类型的指针赋值给父类类型的指针。
“duck typing” 就是一个长得像鸭子,而且也有鸭子的特点的,我们就可以称他为鸭子;比如一只鸟走起来像鸭子、游泳起来像鸭子、叫起来也像鸭子,那么这只鸟就可以被称为鸭子。
type Greeting interface {
SayHello()
GetName()string
}
type Student struct{
Name string
}
func (s Student) SayHello() {
fmt.Printf("hello %s, stu\n",s.Name)
}
func (s Student) GetName() string {
return s.Name
}
func (t Teacher) SayHello() {
fmt.Printf("hello %s, teacher\n", t.Name)
}
func (t Teacher) GetName() string {
return t.Name
}
type Teacher struct{
Name string
}
func main(){
var greet Greeting
s := Student{Name:"Cui"}
t := Teacher{Name:"Duan"}
greet = s
name := greet.GetName()
fmt.Println(name)
greet.SayHello()
greet = t
name = greet.GetName()
fmt.Println(name)
greet.SayHello()
}
python的多态会使用一个函数来辅助实现,通过传递不同的实现了某个函数的class对象来达到不同的效果。
class Greeting(object):
def __init__(self, name):
self.name = name
def say_hello(self):
raise NotImplementedError
def get_name(self):
raise NotImplementedError
class Student(Greeting):
def __init__(self, name):
super(Student,self).__init__(name)
def say_hello(self):
print(f"hello {self.name}, stu")
def get_name(self):
return self.name
class Teacher(Greeting):
def __init__(self,name):
super(Teacher,self).__init__(name)
def say_hello(self):
print(f"hello {self.name}, teacher")
def get_name(self):
return self.name
def hello(obj):
if hasattr(obj, "say_hello"):
obj.say_hello()
else:
print("have not say_hello func.")
if __name__ == '__main__':
s = Student("Cui")
t = Teacher("Duan")
hello(s)
hello(t)