golang 代理_golang协程和线程的区别

go (3) 2024-06-26 20:23

Hi,大家好,我是编程小6,很荣幸遇见你,我把这些年在开发过程中遇到的问题或想法写出来,今天说一说
golang 代理_golang协程和线程的区别,希望能够帮助你!!!。

来自一个大佬的博客,建议食用

设计模式不分语言,是一种思维层面的体现,但是不能在不同语言中使用同一套实现(每种语言有不同的特性),比如go,本身是没有继承一说,但是通过结构体的组合来实现语义上的继承。而多态也是通过接口的方式来实现的。

下方的图来自于大佬博客,贴在这里方便查看!!!

设计原则

golang 代理_golang协程和线程的区别_https://bianchenghao6.com/blog_go_第1张

设计模式

golang 代理_golang协程和线程的区别_https://bianchenghao6.com/blog_go_第2张

结构型模式

代理模式

首先,我们知道代理模式中分为静态代理和动态代理。静态代理需要在编译前就要写好,而动态代理需要在运行时通过反射来实现方法增强。
上述的话,太过粗糙,下面列举一下双方的区别:

静态代理:

  • 代理类实现和目标类相同的接口,每个类都单独编辑一个代理类。
  • 我们需要在代理类中,将目标类中的所有方法都要重新实现,并且为每个方法都附加相似的代码逻辑。
  • 如果要添加方法增强的类不止一个,我们需要对每个类都创建一个代理类。

动态代理:

  • 不需要为每个目标类编辑代理类。
  • 在程序运行时,系统会动态地创建代理类,然后用代理类替换掉原始类。
  • 一般采用反射实现。

代理模式的优点:

  • 代理模式能将代理对象与真实被调用目标对象分离。
  • 在一定程度上降低了系统的耦合性,拓展性好。
  • 可以起到保护目标对象的作用。
  • 可以增强目标对象的功能。

代理的应用场景:

  • 监控
  • 统计
  • 鉴权
  • 限流
  • 事务

静态代理

这里很好看懂,不需过多赘述。

import ( "fmt" "time" ) //静态代理 //就是对目标类提前实现一个代理类,在调用时使用代理类即可 //代理时需要实现目标类的全部方法 type IUser interface { 
    Login(username, password string) error } type User struct { 
    } func (u *User) Login(username, password string) error { 
    //这里就是目标类的函数处理逻辑 return nil } //接下来是代理上述User结构体 type UserProxy struct { 
    //有点挟天子以令诸侯,哈哈哈,开个玩笑 user *User } func NewUserProxy(user *User) *UserProxy { 
    //返回静态代理类 return &UserProxy{ 
    user: user, } } func (p *UserProxy) Login(username, password string) error { 
    //这里就代理一个程序消耗计时功能 start := time.Now() err := p.user.Login(username, password) if err != nil { 
    return err } //其实这里用defer栈也可以 fmt.Printf("调用该程序用时:%v",time.Since(start)) return nil } 

动态代理

思路:仿照java动态代理的思路,通过InvocationHandler来提供Invoke接口,然后用Proxy结合接口去生成代理类,这个接口需要用户自己实现自有逻辑。

//提供动态调用方法接口 type InvocationHandler interface { 
    Invoke(proxy *Proxy, method *Method, args []interface{ 
   }) ([]interface{ 
   }, error) } //代理,用来总管代理类的生成 type Proxy struct { 
    target interface{ 
   } //目标类,后面的类型和java的Object一样 methods map[string]*Method //map用来装载待增强的不同的方法 handle InvocationHandler //用来暴露统一invoke接口,类似多态 } //创建新的代理 func NewProxy(target interface{ 
   }, h InvocationHandler) *Proxy { 
    typ := reflect.TypeOf(target) //用来显示目标类动态的真实类型 value := reflect.ValueOf(target) //获取目标类的值 methods := make(map[string]*Method, 0) //初始化目标类的方法map //将目标类的方法逐个装载 for i := 0; i < value.NumMethod(); i++ { 
    method := value.Method(i) methods[typ.Method(i).Name] = &Method{ 
   value: method} } return &Proxy{ 
   target: target, methods: methods, handle: h} } //代理调用代理方法 func (p *Proxy) InvokeMethod(name string, args ...interface{ 
   }) ([]interface{ 
   }, error) { 
    return p.handle.Invoke(p, p.methods[name], args) } //用来承载目标类的方法定位和调用 type Method struct { 
    value reflect.Value //用来装载方法实例 } //这里相当于调用原方法,在该方法外可以做方法增强,需要调用者自己实现!!! func (m *Method) Invoke(args ...interface{ 
   }) (res []interface{ 
   }, err error) { 
    defer func() { 
    //用来捕捉异常 if p := recover(); p != nil { 
    err = errors.New(fmt.Sprintf("%s", p)) } }() //处理参数 params := make([]reflect.Value, 0) if args != nil { 
    for i := 0; i < len(args); i++ { 
    params = append(params, reflect.ValueOf(args[i])) } } //调用方法 call := m.value.Call(params) //接收返回值 res = make([]interface{ 
   }, 0) if call != nil && len(call) > 0 { 
    for i := 0; i < len(call); i++ { 
    res = append(res, call[i].Interface()) } } return } 

测试代码:

func TestMethod_Invoke(t *testing.T) { 
    //这里对活动时长做统计 people := &People{ 
   } //创建目标类 h := new(PeopleProxy) //创建接口实现类 proxy := NewProxy(people, h) //调用方法 ret, err := proxy.InvokeMethod("Work", "打游戏", "学习") if err != nil { 
    fmt.Println(err) } fmt.Println(ret) } //目标类 type People struct { 
    } func (p *People) Work(content string, next string) string { 
    fmt.Println("活动内容是:" + content + ",接下来需要做:" + next) return "all right" } //用户需要自己实现的增强内容,需要实现InvocationHandler接口 type PeopleProxy struct { 
    } //在这里做方法增强 func (p *PeopleProxy) Invoke(proxy *Proxy, method *Method, args []interface{ 
   }) ([]interface{ 
   }, error) { 
    start := time.Now() defer fmt.Printf("耗时:%v\n", time.Since(start)) fmt.Println("before method") invoke, err := method.Invoke(args...) fmt.Println("after method") return invoke, err } 

golang 代理_golang协程和线程的区别_https://bianchenghao6.com/blog_go_第3张

今天的分享到此就结束了,感谢您的阅读,如果确实帮到您,您可以动动手指转发给其他人。

下一篇

已是最新文章

发表回复