41

我正在寻找有关清理以下结构的最佳方法的建议。我知道 Go 没有静态方法,通常最好将功能封装在单独的包中。我的结构类型相互引用,因此由于循环导入,不能在单独的包中声明。

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在结构上调用或类似的方法,而无需在函数本身中写入结构的名称。这样做的惯用方法是什么?

4

4 回答 4

35

GetUser()GetPayment()让我觉得非常清晰和惯用。我不确定你觉得它们有什么不干净的地方。

调用.Get()一个结构来返回另一个结构让我觉得非常奇怪、不清楚和单调。

我认为这可能只是坚持使用成语并相信您会习惯它的情况。

于 2013-09-07T21:53:21.933 回答
25

Golang 不支持构造函数。

改用工厂函数(Effective Go 参考)。约定是使用New前缀:

func NewUser(id int) *User {
    // Returns new User instance
}

构造函数和工厂函数之间的区别在于工厂函数没有“附加”到User结构上。这是一个正常返回的函数,User而类似 Java/C++ 的构造函数是一种修改新创建User的对象的方法。

于 2014-11-25T10:10:03.743 回答
17

有一个Get功能很好;无论如何,它都不是单调的。

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.
于 2013-09-09T21:52:04.310 回答
1

尽管事实并非如此,但调用模拟静态方法的另一种方法如下:

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

根据评论,另一种选择是:

 fmt.Println(Manager{}.MyMethod(15, 25))

最后用指针:

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))

    fmt.Println((&Manager{}).MyMethod(15, 25))
}
于 2019-10-21T11:21:28.890 回答