生成使用反射的 Go 方法集合

huangapple go评论72阅读模式
英文:

Generating Go method set with reflection

问题

在运行时使用反射生成结构体的接口或方法集是可能的。

例如:

type S struct {
    a int
}

func (s *S) Fn(b int) int {
    return s.a + b
}

type I interface {
    Fn(a int) int
}

func main() {
    var x I = &S{a: 5}
    fmt.Printf("%#v\n", x.Fn)
    fmt.Printf("%#v\n", reflect.TypeOf(x).Method(0))

    var y I
    y.Fn = x.Fn // 这里会失败,但我想在运行时设置 y.Fn。
    fmt.Printf("%#v\n", reflect.TypeOf(y).Method(0))
}

https://play.golang.org/p/agH2fQ4tZ_

为了澄清,我正在尝试构建一个中间件库,因此接口 I 包含了 HTTP 处理程序,我想要用某种请求/响应日志记录包装每个处理程序,所以我需要返回一个新的接口 I,其中新接口 I 中的每个函数都包装了原始函数加上一些日志记录。

英文:

Is it possible to generate an interface or method set of a struct at runtime with reflection?

For example:

type S struct {
	a int
}

func (s *S) Fn(b int) int {
	return s.a + b
}

type I interface {
	Fn(a int) int
}

func main() {
	var x I = &S{a: 5}
	fmt.Printf("%#v\n", x.Fn)
	fmt.Printf("%#v\n", reflect.TypeOf(x).Method(0))
	
	var y I
	y.Fn = x.Fn // This fails, but I want to set y.Fn at runtime.
	fmt.Printf("%#v\n", reflect.TypeOf(y).Method(0))
}

https://play.golang.org/p/agH2fQ4tZ_

To clarify, I'm trying to build a middleware library so interface I contains the http handlers and I want to wrap each hander with some sort of req/response logging so I need to return a new interface I where each function in new Interface I wraps the original + some logging.

答案1

得分: 2

这是处理接口I和J的方法:

type I interface { Fn1(a int) int }
type J interface { Fn2(a int) int }

type Y struct {       // Y通过调用fn来实现I
   fn func(a int) int
}

func (y Y) Fn1(a int) int { return y.fn(a) }

type Z struct {       // Z通过调用fn来实现J
   fn func(a int) int
}

func (z Z) Fn2(a int) int { return y.fn(a) }

var y I = Y{fn: x.Fn}
var z J = Z{fn: x.Fn}

不需要使用反射。

playground示例

英文:

Here's how to handle this for interfaces I and J.

type I interface { Fn1(a int) int }
type J interface { Fn2(a int) int }

type Y struct {       // Y implements I by calling fn
   fn func(a int) int
}

func (y Y) Fn1(a int) int { return y.fn(a) }

type Z struct {       // Z implements J by calling fn
   fn func(a int) int
}

func (z Z) Fn2(a int) int { return y.fn(a) }

var y I = Y{fn: x.Fn}
var z J = Z{fn: x.Fn}

There's no need to use reflection.

playground example

huangapple
  • 本文由 发表于 2016年10月31日 02:05:54
  • 转载请务必保留本文链接:https://go.coder-hub.com/40332011.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定