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)。要使用它,必须按照它们在磁盘上的精确顺序在结构中[导出]字段。因此,我不能只嵌入另一个结构的字段,因为在某些记录中它们的顺序不同(且大小不同)
答案 0 :(得分:0)
如果您遇到的问题是某些内容的类型不同,您可以使Time
和User
函数在包含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。