• Go源码解读-registry配置


    前言

    本次解读的源码是go-micro框架中registry仓库的配置,我们通常用以下这段代码来配置etcd

    newRegistry := etcdv3.NewRegistry(func (options *registry.Options) {
    	options.Addrs = []string{"192.168.100.151:2379"}
    })
    
    service := micro.NewService(
    	micro.Registry(newRegistry),
    )
    

    这段代码内部的实现本质在于,创建Registry对象完成,返回对象之前,给该对象配置相关属性。

    解读分析

    我根据源码重新写了一段类似的代码,实现的原理是相同的。这段源码使用函数参数的形式来给生成的实例注入属性。

    package main
    
    import "fmt"
    
    type Animal struct {
    	name string
    }
    
    type Dog struct {
    	animal Animal
    	action string
    }
    
    type AniFunc func (*Animal)
    
    func configure(d *Dog, af ...AniFunc)  {
        /*
        	不断遍历传入的函数,每个函数中的赋值语句都会作用于传参的对象中,更新对应属性
        */
    	for _, o := range af {
            /*
            	核心代码:此时o为对应的函数
            	o := func(animal *Animal) {
                    animal.name = "animal"
                }
                那么此时 &d.animal取到了实例化对象的地址,传给了指针对象参数
                通过指针对象参数,可以直接操作该实例化参数的属性,也就实现了配置信息的注入
            */
    		o(&d.animal)
    	}
    	fmt.Printf("type:%T, value:%+v", d, d)
    }
    
    func NewDog(af ...AniFunc) *Dog {
    	a := &Dog{
    		animal: Animal{},
    	}
    
    	configure(a, af...)
    
    	return a
    }
    
    func main() {
    	NewDog(func(animal *Animal) {
    		animal.name = "animal"
    	}, func(animal *Animal) {  // 后面的属性会覆盖前面相同的属性,即name=lion
    		animal.name = "lion"
    	})
    }
    

    框架源码

    type Option func(*Options)
    
    type etcdRegistry struct {
    	client  *clientv3.Client
    	options registry.Options
    
    	sync.RWMutex
    	register map[string]uint64
    	leases   map[string]clientv3.LeaseID
    }
    
    func NewRegistry(opts ...registry.Option) registry.Registry {
    	e := &etcdRegistry{
    		options:  registry.Options{},
    		register: make(map[string]uint64),
    		leases:   make(map[string]clientv3.LeaseID),
    	}
    	configure(e, opts...)
    	return e
    }
    
    func configure(e *etcdRegistry, opts ...registry.Option) error {
    	config := clientv3.Config{
    		Endpoints: []string{"127.0.0.1:2379"},
    	}
    
    	for _, o := range opts {
    		o(&e.options)
    	}
    
    	if e.options.Timeout == 0 {
    		e.options.Timeout = 5 * time.Second
    	}
    
    	if e.options.Secure || e.options.TLSConfig != nil {
    		tlsConfig := e.options.TLSConfig
    		if tlsConfig == nil {
    			tlsConfig = &tls.Config{
    				InsecureSkipVerify: true,
    			}
    		}
    
    		config.TLS = tlsConfig
    	}
    
    	if e.options.Context != nil {
    		u, ok := e.options.Context.Value(authKey{}).(*authCreds)
    		if ok {
    			config.Username = u.Username
    			config.Password = u.Password
    		}
    	}
    
    	var cAddrs []string
    
    	for _, address := range e.options.Addrs {
    		if len(address) == 0 {
    			continue
    		}
    		addr, port, err := net.SplitHostPort(address)
    		if ae, ok := err.(*net.AddrError); ok && ae.Err == "missing port in address" {
    			port = "2379"
    			addr = address
    			cAddrs = append(cAddrs, net.JoinHostPort(addr, port))
    		} else if err == nil {
    			cAddrs = append(cAddrs, net.JoinHostPort(addr, port))
    		}
    	}
    
    	// if we got addrs then we'll update
    	if len(cAddrs) > 0 {
    		config.Endpoints = cAddrs
    	}
    
    	cli, err := clientv3.New(config)
    	if err != nil {
    		return err
    	}
    	e.client = cli
    	return nil
    }
    
    
    
  • 相关阅读:
    ros 使用命令测试topic
    python unicode
    python ros 回充demo
    python ros 回充调用demo
    flask报错No module named 'flask.ext'
    python flask 接口
    ros 安装c++编译的可执行文件
    Linux-Ubuntu14.04下mongodb安装部署
    如何在Ubuntu 14.04中安装最新版Eclipse
    ubuntu 14.04 安装redis5.0.3
  • 原文地址:https://www.cnblogs.com/zimskyzeng/p/14412314.html
Copyright © 2020-2023  润新知