如 php:
class a
{
public function __call($method, $args) {
return call_user_func([new b(), $method], $args);
}
}
class b {}
不能是 xx.call('method',...)
最好还是 xx.method
场景是 三方包 不想改,三方包里要 xxx(handler{})
然后 handler 里有一些方法。想实现在三方包调用 handler.xx 的时候先经过一次自己的验证。
否则 handler 可能就要写成
func (h *handler) m1 {
if h.xx == nil {
// xx
}
}
func (h *handler) m2 {
if h.xx == nil {
// xx
}
}
func (h *handler) m3 {
if h.xx == nil {
// xx
}
}
1
superfatboy 2022-03-10 13:30:53 +08:00
貌似 好像 iris 有一个这个功能,能在路由前置执行,不知道符合不符合你的要求
|
2
mybyons 2022-03-10 13:45:05 +08:00
Wrapper / Adapter
```go func log(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log.Println("Before") h.ServeHTTP(w, r) // call original log.Println("After") }) } ``` http.Handle("/path", handleThing) --> http.Handle("/path", log(handleThing)) |
3
mybyons 2022-03-10 13:46:29 +08:00
Wrapper / Adapter
```go func log(h http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { log.Println("Before") h.ServeHTTP(w, r) // call original log.Println("After") }) } ``` http.Handle("/path", handleThing) --> http.Handle("/path", log(handleThing)) |
4
wangritian 2022-03-10 14:35:18 +08:00
go 没有魔术方法,只能自己包一层
|
5
james122333 2022-03-10 18:39:20 +08:00
__call 如果没做其他什么直接 type embeding 就可以
有的话只能用反射外包一层 并且方法必须要是 field 不能是 struct 内 method 不然完全找不到 Address... |
6
james122333 2022-03-10 19:00:20 +08:00
可以自己写个 lib 用来初始化 类似 new 或者依赖注入都可以 乍看之下风格是差不多的 type embeding 的状况这些函数 field 也会有
|
7
james122333 2022-03-10 19:01:58 +08:00
你要用对象写是会很痛苦的
|
8
Goooooos 2022-03-10 19:32:22 +08:00 via Android
这不符合 go 的设计思想
|
9
dobelee 2022-03-11 01:29:22 +08:00
是要实现类似统一参数校验的效果吗?这种一般包多一层 middleware ,相反 php 的魔术方法才是奇葩实现(相比其他主流)。
|
10
lwldcr 2022-03-11 07:42:06 +08:00 via iPhone
Middleware 或者叫拦截器 差不多就这样 把方法作为参数
|
11
sampeng 2022-03-11 08:32:27 +08:00 via iPhone
出门右拐用 java ,python ,php ,等灯
|
12
MeetTheFuture 2022-03-11 10:07:54 +08:00
Middleware
|
13
bugfan 2022-03-11 10:35:21 +08:00
自己包装一层中间件,可以放在主要逻辑前,也可以放在主要逻辑后 类似 https://github.com/bugfan/srv
|
14
dzdh OP @james122333
就是重写一遍 struct 挨个实现其方法。然后再方法内挨个走我自己的方法再调他原有的方法? ``` type o struct{} func (_o *o) m1() { } type my struct { o } func (_my *my) m1() { // before _my.o.m1() // 或者我在 my 里再写个统一的 wrapper ? // after } ``` 然后 ` xxx.handle(&my{}) ` ? 就是麻烦点。。 |
15
james122333 2022-03-11 18:01:36 +08:00
@dzdh
这只是 type embedding 如果要实现你要的风格 并且有其他动作 就得替换方法包一层 每个都要呼叫魔术方法 另外反射讲的是写个 library 把下列类似代码串起来(反射再包一层的方法是 reflect.MakeFunc) 然后如何初始化 struct 内 func 自己想想 毕竟每次 new 一个出来还要指定哪个 func 很麻烦 所以才会有后面那个`bind` 主要是透过 reflect.MakeFunc 替换原来 func field 指定先做魔术方法再做原来的方法 type Test struct { Call func(t *Test) `bind:"Call"` A func(t *Test) `bind:"A"` } var Call = func(t *Test) { fmt.Println("Call") } var A = func(t *Test) { fmt.Println("A") } |
16
james122333 2022-03-11 18:26:48 +08:00 via Android
那个 A 函数只要透过 makefunc 把 call 函数并入一次就可以 比较麻烦的是怎么让一切自动完成
|
17
bugfan 2022-03-11 19:28:57 +08:00
@dzdh #14 这种还不算是最优解,其实可以参考一些框架的设计都用了反射,例如:
``` type magic interface { Call(*some.Class) } // 把你的 model 传进去 func Register(m interface{}){ handlers=append(handlers,m) } // 在合适的时机执行 func bind(h interface{}){ // 一些逻辑处理 handlers reflectVal := reflect.ValueOf(h) t := reflect.Indirect(reflectVal).Type() newObj := reflect.New(t) handler, ok := newObj.Interface().(magic) if ok { handler.Call(xxxx) } // 然后走你 register 进去的 model 的逻辑 } // 类似 “https://github.com/bugfan/rest/blob/master/rest.go”,不喜轻喷啊😂 ``` |
18
dzdh OP |
19
kongkongyzt 2022-03-12 09:48:14 +08:00
无...
|
20
james122333 2022-03-12 20:04:55 +08:00 via Android
|