Go - 围绕界面切片问题的惯用法

时间:2014-05-22 10:27:44

标签: go

我有一个WorkDay结构,其中包含有关某人工作时间的数据,一个WorkWeek结构来保存一堆WorkDays,以及一个WorkMonth结构来保存一堆WorkWeek。我们的想法是让每个人返回在此期间工作的总时数。

type WorkDay struct {
    StartTime time.Time
    EndTime   time.Time
}

type WorkWeek struct {
    WorkDays []WorkDay
}

type WorkMonth struct {
    WorkWeeks []WorkWeek
}

func (w WorkDay) HoursWorked() time.Duration {
    // Find hours worked through simple subtraction.
}

func (w WorkWeek) HoursWorked() time.Duration {
    var totalHours time.Duration
    for _, day := range w.WorkDays {
        totalHours += day.HoursWorked()
    }
    return totalHours
}

func (w WorkMonth) HoursWorked() time.Duration {
    var totalHours time.Duration
    for _, week := range w.WorkWeeks {
        totalHours += week.HoursWorked()
    }
    return totalHours
}

这段代码工作得很好,但WorkWeek.HoursWorked()WorkMonth.HoursWorked()中的重复确实让我感觉不舒服。我试着做以下事情,以为我很聪明:

func (w WorkWeek) HoursWorked() time.Duration {
    return sumHoursWorked(w.WorkDays)
}

func (m WorkMonth) HoursWorked() time.Duration {
    return sumHoursWorked(m.WorkWeeks)
}

type countable interface {
    HoursWorked() time.Duration
}

func sumHoursWorked(timeFrames []countable) time.Duration {
    var totalHours time.Duration
    for _, frame := range timeFrames {
        totalHours += frame.HoursWorked()
    }
    return totalHours
}

但是,正如here所述,尽管WorkDay实现了countable,但WorkDay的切片不算作countable的切片。

那么,是否有一些漂亮的,惯用的方式摆脱了我所遗漏的情况,或者我只是坚持复制?

2 个答案:

答案 0 :(得分:4)

没有。要么有一片countables,它会为您提供动态方法调度或一些编程(您的第一个解决方案)或重组您的类型。我不知道你的问题域,但几个星期组成的几个月似乎很奇怪,至少是月/周的东西。

答案 1 :(得分:2)

否,因为countables的切片是另一种类型。 您可以定义自己的切片类型并为其附加Add方法。

func (w WorkWeek) HoursWorked() time.Duration {
    return sumHoursWorked(w.WorkDays)
}

func (m WorkMonth) HoursWorked() time.Duration {
    return sumHoursWorked(m.WorkWeeks)
}

type countable interface {
    HoursWorked() time.Duration
}

type SliceCountable []countable

func (m *SliceCountable) Add( c countable ) {
   *m = append(*m, c ) 
}

func (m SliceCountable) HoursWorked() time.Duration {
var totalHours time.Duration
for _, frame := range m {
    totalHours += frame.HoursWorked()
}
return totalHours
}


func sumHoursWorked(timeFrames []countable) time.Duration {
    var totalHours time.Duration
    for _, frame := range timeFrames {
        totalHours += frame.HoursWorked()
    }
    return totalHours
}