3

谈Go装饰器及其应用

 2 years ago
source link: https://allenwind.github.io/blog/3911/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client
Mr.Feng Blog

NLP、深度学习、机器学习、Python、Go

谈Go装饰器及其应用

Python的一个重要语法特性是装饰器,它本身还提供了’@’这样优雅的语法糖使用装饰器。装饰器本质上是闭包的一个应用。Go支持闭包,也就可以说Go也支持装饰器,只是Go编译器提供的“糖”太小了,不能像Python一样优雅地使用装饰器。但,这并不阻碍我们使用装饰器这个方便的特性。

闭包是一个函数返回值,该返回值依然是一个函数。这个函数携带函数外部定义的变量。可以把这个外部变量理解为闭包的初始状态。

我们看看JavaScript的实现

function Counter() {
var n = 0;
return function incr() {
retrun n + 1;
}
}

var counter = Counter();
counter() // 1
counter() // 2

对比Python的实现

def Counter():
n = 0
def incr():
nonlocal n
n = n + 1
return n
return incr

c = Counter()
c() // 1
c() // 2

这样,内部函数incr都携带Counter函数内部的n状态。

一个简单的示例

关于装饰器,先来一个简单的示例:

package main

import (
"fmt"
)

func decorator(f func(s string)) func(s string) {
return func(s string) {
fmt.Println("start func...")
f(s)
fmt.Println("end func...")
}
}

func inner(s string) {
fmt.Println("I am inner function", s)
}

func test() {
fn := decorator(inner)
fn("one")
}

func main() {

test()
}

inner函数被decorator装饰过后返回fn。

和Python的比较

对比Python的实现

from functools import wraps

def decorator(func):
@wraps(func)
def wrapper(*args, **kwargs):
print("start func...")
func(*args, **kwargs)
print("end func...")
return wrapper

@decorator
def inner(s):
print("I am inner function", s)

def main():
inner()

对比下,Go就小’@’,但可以通过传入函数代替。’@’本身在Python中也是传入函数的语法糖。

Go装饰器的一个应用

使用装饰器来计算函数运算时间。

package main

import (
"fmt"
"time"
)

func fib(n uint) uint {
if n == 0 || n == 1 {
return 1
} else {
return fib(n-1) + fib(n-2)
}
}

type Fib func(n uint) uint

func timedFunc(f Fib) Fib {
return func(n uint) uint {
defer func(t time.Time) {
fmt.Println("elapsed time is ", time.Since(t))
}(time.Now())
return f(n)
}
}

func main() {
fib_timer := timedFunc(fib)
fmt.Println(fib_timer(30))
}

另外还可以实现计时、定时执行、HTTP装饰等,终止Python的装饰器技巧都可以搬到Go上,只是后者没有那么多”糖”。


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK