Ano*_*use 4 oop struct embedding law-of-demeter go
这就是有效GO关于嵌入 golang的内容
当我们嵌入一个类型时,该类型的方法成为外部类型的方法,但是当它们被调用时,方法的接收者是内部类型,而不是外部类型.
我有一个代码片段,我在其中Struct User定义如下
type User struct {
Name string
Password string
*sql.Tx
}
Run Code Online (Sandbox Code Playgroud)
然后我打电话u.Query("some query here")等.我已经专门做了这个,这样我就可以避免这样的电话u.Transaction.Query("query"),这显然违反了得墨忒耳法则.现在,在阅读了文档和有效的文章后,我对第一种方法的优点也表示怀疑.我违反了得墨忒耳法吗?如果是,我该如何避免呢?
嵌入概念有点违反得墨忒耳定律,因为它并不能掩盖一个类型嵌入的事实,如果该类型本身是出口.请注意,嵌入一个未导出类型不违反毁灭之王(你不能引用未导出字段和方法).
但这并不会强迫您以违反LoD的方式引用提升的字段或方法.嵌入本身只是一种技术,因此您可以将常见的共享代码"外包"到其他类型; 或者从另一个角度来创建新的类型时使用其他类型.您引用嵌入类型的提升字段或方法的方式可能违反法律.
正如你所说,如果你称之为,那就u.Tx.Query()明显违反了得墨忒耳法则:你正在使用User嵌入的实现细节*sql.Tx.
但如果你这样称呼它:u.Query()那没关系.此表单不会暴露或利用*sql.Tx嵌入的事实.如果实现发生更改并且*sql.Tx不再嵌入(例如,将其更改为"常规"字段或完全删除,并User.Query()添加方法),此表单将继续有效.
如果您不想允许访问导出的嵌入类型的字段值,请将其设为未导出的常规字段,并添加User.Query()可以委托给该字段的"显式" 方法,例如:
type User struct {
Name string
Password string
tx *sql.Tx // regular field, not embedded; and not exported
}
func (u *User) Query(query string, args ...interface{}) (*sql.Rows, error) {
return u.tx.Query(query, args...)
}
Run Code Online (Sandbox Code Playgroud)
附加说明:
在该示例中,如果u.Query()使用if,则使用它的客户端不会受到影响,如果内部User更改(如果u.Query()表示提升的方法或表示方法User,则无关紧要,即:)User.Query().
如果sql.Tx更改,是的,u.Query()可能不再有效.但sql.Tx不太可能发生不相容的情况.如果您是更改的软件包的开发人员,并进行了不兼容的更改,则您有责任更改依赖于不兼容更改的其他代码.这样做(正确更新u.Query())调用的客户端u.Query()不会受到影响,客户端仍然不需要知道改进后的内容.
这正是LoD所保证的:如果您使用u.Query()而不是u.Tx.Query(),如果User内部更改,客户端调用u.Query()不需要知道或担心.LoD并不是件坏事.你不应该放弃它.你可以选择你遵循的原则,但是你也应该思考而不是遵循一切选择的原则,不惜一切代价.
还有一件事要清楚:LoD不涉及API不兼容的更改.它提供的是如果遵循,实体的内部变更将不会对使用该实体的"公共"面的其他实体产生影响.如果sql.Tx以一种Tx.Query()不再可用的激烈方式进行更改,则LoD不会"覆盖".