假设我有一个类型type T int
,我想定义一个逻辑来操作这种类型。
我应该使用什么抽象和什么时候?
在该类型上定义方法:
func (T t) someLogic() {
// ...
}
定义功能:
func somelogic(T t) {
// ...
}
答案 0 :(得分:5)
您倾向于使用方法的一些情况:
x.Foo
修改X而不是Foo(x)
的用户来说,这并不奇怪。struct
s。friend
定义为带有方法而不是函数的空结构,只是为了满足与不是的其他实现相同的type openWeatherMap
接口。 em>空结构。
您倾向于使用功能的地方:
weatherProvider
是一个函数,而不是一个方法。 Go没有构造函数的概念,因此它必须如此。func NewFoo(...) (*Foo)
或基本类型上添加方法(除非您使用interface
使其成为新类型)。因此,type
和strings.Split
必须是函数。此外,reflect.DeepEqual
必须是一个函数,因为它不能只在io.Copy
或Reader
上定义方法。请注意,这些并未声明新类型(例如,Writer
)以避免无法对基本类型执行方法。strings.MyString
或User
)会积累大量功能,并且会造成伤害可读性或组织甚至导致结构性问题(如果变得难以避免cyclic imports)。使不突变接收器,访问未导出的字段等的方法中的非方法可能是将其代码“向上”移动到应用程序的更高层的重构步骤或“over”到另一个类型/包,或者独立功能只是它最自然的长期地方。 (帽子提示Steve Francia包括hugo中关于他的Go错误的一个例子。)Page
是一个包级别的函数,可以使http.ListenAndServe()
变得微不足道,并在其上调用http.Server
。ListenAndServe
或{{ 1}}或用于注册http.HandleFunc()
支票等。不要强迫它。template.Funcs()
或go vet
更干净看看任何对象字段,永远不会。再说一遍,如果在你的情况下,你没有获得任何东西,不要觉得你必须强迫OO(àlamain()
)。如果有疑问,如果某些内容是您导出的API的一部分,并且可以自然选择将其附加到哪种类型,请将其作为方法。但是,不要扭曲你的设计(将问题拉入你的类型或包装中可能是分开的),这样就可以成为一种方法。 init()
不type Application struct{...}
;如果他们这样做的话,很难实现。相反,您通过其他地方Writer
添加了WriteJSON
的JSON功能。
如果您仍然不确定,请首先编写以便文档清晰显示,然后使代码自然地读取(Writer
或json.NewEncoder(w io.Writer)
),然后选择感觉正确而不会出汗的情况很多,因为通常你可以稍后重新安排它。
答案 1 :(得分:3)
如果您正在操纵对象的内部secrets
(T *t) func someLogic() {
t.mu.Lock()
...
}
如果您使用对象的public interface
func somelogic(T *t) {
t.DoThis()
t.DoThat()
}
答案 2 :(得分:0)
如果要更改T对象,请使用
func (t *T) someLogic() {
// ...
}
如果您不想更改T对象并希望采用对象方式,请使用
func (t T) someLogic() {
// ...
}
但请记住,这会生成一个临时对象T来调用someLogic
如果您喜欢c语言的方式,请使用
func somelogic(t T) {
t.DoThis()
t.DoThat()
}
或
func somelogic(t T) {
t.DoThis()
t.DoThat()
}
还有一件事,类型是golang中的var。