我正在寻找有关清理以下结构的最佳方法的建议。我知道Go没有静态方法,通常是better to encapsulate functionality in a separate package。我的结构类型互相引用,因此不能在单独的包中声明,因为循环导入。
type Payment struct {
User *User
}
type User struct {
Payments *[]Payments
}
func (u *User) Get(id int) *User {
// Returns the user with the given id
}
func (p *Payment) Get(id int) *Payment {
// Returns the payment with the given id
}
但是,如果我想加载用户或付款,我只是扔掉接收器:
var u *User
user := u.Get(585)
我可以命名函数本身,这让我觉得不洁净:
func GetUser(id int) *User {
// Returns the user with the given id
}
func GetPayment(id int) *Payment {
// Returns the payment with the given id
}
我真的希望能够在结构上调用.Get
或类似的东西,而无需在函数本身中编写结构名称。这样做的惯用方法是什么?
答案 0 :(得分:26)
GetUser()
和GetPayment()
让我觉得非常明确和惯用。我不确定你发现什么是不洁净的。
在结构上调用.Get()
以返回另一个结构是令我感到非常奇怪,不清楚和单一的结构。
我认为这可能只是坚持使用成语并相信你会习惯它。
答案 1 :(得分:15)
具有Get
功能完全没问题;它不以任何方式 unidiomatic 。
func (u *User) Get(id int) *User
没有任何意义,但它应该是func (u *User) Get(id int) error
。您缺少的一件事是您可以在指针上定义方法接收器,然后在该方法内部取消引用指针以覆盖它指向的内容。
像这样:
// Returns the user with the given id
func (u *User) Get(id int) error {
*u = User{ ... } // dereference the pointer and assign something to it
return nil // or an error here
}
如果有任何问题,请返回错误。现在你可以说
type Getter interface {
Get(int) error
}
因此可以定义任何定义Get(id)error
的类型。然后你会像这样使用它:
u := new(User)
if err := u.Get(id); err != nil {
// problem getting user
}
// everything is cool.
答案 2 :(得分:13)
Golang不支持构造函数。
改为使用工厂功能(Effective Go reference)。惯例是使用New
前缀:
func NewUser(id int) *User {
// Returns new User instance
}
构造函数和工厂函数之间的区别在于工厂函数不是"附加"到User
结构。它是一个正常函数,碰巧返回User
,而类似Java / C ++的构造函数是一个修改新创建的User
对象的方法。
答案 3 :(得分:0)
另一种调用模拟静态方法的方法(尽管事实并非如此)如下:
package main
import "fmt"
type Manager struct {
}
func (m Manager) MyMethod(a float32, b float32) float32 {
return 0.5 * a * b
}
func main() {
fmt.Println((Manager).MyMethod(Manager{}, 15, 25))
}
但是从我的角度来看,这比将方法放置在类manager
之外的单独包Manager
中要难理解