Golang:代码重复和类似的结构

时间:2015-10-09 20:59:40

标签: go

Go to to superclass类似(但不完全相同)的数据类型以减少代码重复的惯用方法是什么? Trite示例:

import "time"

type LinuxUtmp struct {
    ut_type uint16
    _       [2]byte
    ut_pid  uint32
    ut_line [32]byte
    ut_id   [4]byte
    ut_user [32]byte
    ut_host [256]byte
    exit_status [2]uint32
    tv_sec  uint32
    tv_usec uint32
    ...
}

func (l LinuxUtmp) User() string {
    return string(l.ut_user[:])
}

func (l LinuxUtmp) Time() time.Time {
    return time.Unix(int64(l.tv_sec), int64(l.tv_usec))
}

type BsdUtmp struct {
    ut_line [8]char
    ut_name [16]char
    ut_host [16]char
    ut_time uint32
}

func (b BsdUtmp) User() string {
    return string(b.ut_user[:])
}

func (b BsdUtmp) Time() time.Time {
    return time.Unix(int64(b.ut_time), 0)
}

显然还有更多的东西,但是我希望能够以某种方式超级分类,所以我只需要编写和维护一个特定功能的副本。界面似乎是"对"方式,但还有很多不足之处(非工作示例):

type Utmp interface {
    Time() time.Time
}

func User(u Utmp) string {
    return string(u.ut_user[:])
}

我也考虑过嵌入,但由于Go是如此严格打字,这似乎也是一个死胡同。我注定要拥有多条代码,除了签名之外,各方面都相同吗?

[编辑]

部分复杂性是我使用encoding / binary.Read()根据字节顺序解析这些数据(它不仅仅是utmp记录而不仅仅是Linux / BSD)。要使用它,必须按照它们在磁盘上的精确顺序在结构中[导出]字段。因此,我不能只嵌入另一个结构的字段,因为在某些记录中它们的顺序不同(且大小不同)

2 个答案:

答案 0 :(得分:0)

如果您遇到的问题是某些内容的类型不同,您可以使TimeUser函数在包含linux和bsd功能的接口上运行。

如果您不喜欢,可以生成代码以避免重复。

答案 1 :(得分:0)

我不理解您对嵌入的评论。我是这样做的(使用嵌入):

package test

import "time"

type Utmp struct {
    // Common fields
}

func (u Utmp) User() {
    return string(l.ut_user[:])
}

type LinuxUtmp struct {
    Utmp
    // Linux specific fields
}

func (l LinuxUtmp) Time() time.Time {
    return time.Unix(int64(l.tv_sec), int64(l.tv_usec))
}

type BsdUtmp struct {
    Utmp
    // BSD specific fields
}

func (b BsdUtmp) Time() time.Time {
    return time.Unix(int64(b.ut_time), 0)
}

导入库的任何代码都可以直接在User()LinuxUtmp个对象上直接调用BsdUtmp方法l.User()b.User(),而不提及Utmp一点都不如果您愿意,甚至可以保留Utmp意外(utmp)。

查看Effective Go了解详情。

如果愿意,您甚至可以确保只有用于相关平台的代码才能在二进制文件中编译。 This blog有一些例子。为了保持简单,如果特定于平台的代码不是很大或者涉及其他因素,我就不会打扰这条路线。

为了完整起见,这是官方go build doc。