美文网首页
golang project exp02

golang project exp02

作者: wangrui927 | 来源:发表于2019-10-25 18:42 被阅读0次

谷歌SRE那本书中所讲到一点,就是搞业务运维或说SRE,最头疼的就是工作量随着服务规模的增长线性增加。其实个人觉得这一点放到开发中也是一样的,随着需求的增加,services、views目录下的文件越来越多,编写它们的时候都是copy&paste,维护它们的时候也是一样的任务量复制。
就其根源,个人觉得就是我们所谓“开发”对工程规范的漠视,导致维护过程中问题的累积。这里也记录一点过去积累的好的编码习惯(针对golang而言)

1,创建一个较为复杂的对象时,把New函数参数可选
比如说

type MyOperation struct {
    keyone string
    valone int
    someConfig bool
    someConfig2 bool
    storage *db.Connection
}

type Opt interface {
    apply(*MyOperation)
}

type optFunc func(o *MyOperation) 

func (f optFunc) apply(o *MyOperation) {
    f(o)
}

func WithStorage(src *db.Connection) Opt {
    return optFunc(func(o *MyOperation) {
        o.storage = src
    }
}

func WithConfig(conf bool) Opt {
    ...
}

func NewOperation(mustKey string, ... Opt) (*MyOperation, error) {
    op := &MyOperation {
        keyone : mustKey,
    }
    for _, optFunc := range Opt {
        optFunc(op)
    }
    return op, nil
}

我刚开始的时候很不理解,把一个NewOperation写这么有什么好处。但是后来发现,代码结构、可读性是真的非常重要。特别运维开发这块,国内现在就是一个起步过程,运维开发存在很多任务都是对之前代码的重构与功能维护。
我相信干过一段时间你就知道阅读别人代码的痛苦吧,可能搞懂逻辑就要花好几天,但是写代码不过一两天、两三天而已。

2,多写注释,如果一个函数参数很多,甚至可以给参数加注释,特别是我们一个操作对象,可能有n多个配置,如
func someOperation(true, true, false, false, true,...)
并且这个函数可能会在一个代码文件中出现多次,可能每次这些布尔配置参数还不一样,所以有必要加一点说明
func someOperation(true /* 允许重试/, true, false, false / 不记失败日志等*/,...)

3,减少作用域

... 上文中已经存在err 错误对象, 这个err可能并不希望被覆盖掉

if f, err := someOpt(); err != nil {
    return err
}
f.xxx()

4,开关策略(这条是摘抄来的)
生产环境上的所有操作都是需要严格按照策略进行,那么就需要添加一个开关机制,我之前项目并未应用这种机制,确实带来了不少麻烦,所以这里可以摘录一下

package switches


var (
    xxxSwitchManager = SwitchManager{switches: make(map[string]*Switch)}
    
   AsyncProcedure = &Switch{Name: "xxx.msg.procedure.async", On: true}

    // 使能音视频
    EnableRealTimeVideo = &Switch{Name: "xxx.real.time.video", On: true}

)

func init() {
    xxxSwitchManager.Register(AsyncProcedure, 
    EnableRealTimeVideo)
}


// 具体实现结构和实现方法
type Switch struct {
    Name      string
    On        bool
    listeners []ChangeListener
}

func (s *Switch) TurnOn() {
    s.On = true
    s.notifyListeners()
}

func (s *Switch) notifyListeners() {
    if len(s.listeners) > 0 {
        for _, l := range s.listeners {
            l.OnChange(s.Name, s.On)
        }
    }
}

func (s *Switch) TurnOff() {
    s.On = false
    s.notifyListeners()
}

func (s *Switch) IsOn() bool {
    return s.On
}

func (s *Switch) IsOff() bool {
    return !s.On
}

func (s *Switch) AddChangeListener(l ChangeListener) {
    if l == nil {
        return
    }
    s.listeners = append(s.listeners, l)
}

type SwitchManager struct {
    switches map[string]*Switch
}

func (m SwitchManager) Register(switches ...*Switch) {
    for _, s := range switches {
        m.switches[s.Name] = s
    }
}

func (m SwitchManager) Unregister(name string) {
    delete(m.switches, name)
}

func (m SwitchManager) TurnOn(name string) (bool, error) {
    if s, ok := m.switches[name]; ok {
        s.TurnOn()
        return true, nil
    } else {
        return false, errors.New("switch " + name + " is not registered")
    }
}

func (m SwitchManager) TurnOff(name string) (bool, error) {
    if s, ok := m.switches[name]; ok {
        s.TurnOff()
        return true, nil
    } else {
        return false, errors.New("switch " + name + " is not registered")
    }
}

func (m SwitchManager) IsOn(name string) (bool, error) {
    if s, ok := m.switches[name]; ok {
        return s.IsOn(), nil
    } else {
        return false, errors.New("switch " + name + " is not registered")
    }
}

func (m SwitchManager) List() map[string]bool {
    switches := make(map[string]bool)
    for name, switcher := range m.switches {
        switches[name] = switcher.On
    }
    return switches
}

type ChangeListener interface {
    OnChange(name string, isOn bool)
}


// 这里开始调用
if switches.AsyncProcedure.IsOn() {
    // do sth
}else{
    // do other sth
}

并且这里可以看到的,switch对象中的name是通过点进行分隔的,这也是SRE中所说的,所有配置信息都应有清晰的命名标准,并且所有成员都可以了解到这些配置项

相关文章

网友评论

      本文标题:golang project exp02

      本文链接:https://www.haomeiwen.com/subject/msjsvctx.html