[英]How do I access a method expression (struct function) from within another method expression in Go / Golang?
我正在嘗試清理我的Go / Golang項目中的代碼。 我認為以一種面向對象的方式創建模型可能是慣用的,例如:
db.Users.GetID("john")
(在“用戶”表中做某事) db.Purchases.GetTotal()
(在“ db.Purchases.GetTotal()
”表中做某事) 但是,這樣做的一個問題是,數據庫函數無法根據需要自行調用。
這是我所談論的一個小巧的示例:
package main
import "fmt"
// A model that contains all of the structs for our database tables
type Model struct {
Users
Purchases
}
// A struct for functions that have to do with the "users" table
type Users struct {}
func (self *Users) Exists(id int) bool {
// Check to see if the user exists
// SELECT id FROM users WHERE id = ?
return true // (omitted)
}
// A struct for functions that have to do with the "purchases" table
type Purchases struct {}
func (self *Purchases) Count(id int) int {
// First validate that the user exists
if db.Users.Exists(id) == false { // This fails <--------------
return 0
} else {
// Get the count of that user's purchases
// SELECT COUNT(user_id) FROM purchases WHERE user_id = ?
return 50 // (omitted)
}
}
func main() {
db := Model{}
numPurchases := db.Purchases.Count(123)
if numPurchases != 0 {
fmt.Println("User #123 has", numPurchases, "purchases!")
} else {
fmt.Println("User #123 does not exist!")
}
}
這會導致錯誤:
undefined: db in db.Users
如果我將其更改為Users.Exists
而不是db.Users.Exists
:
./test.go:22: invalid method expression Users.Exists (needs pointer receiver: (*Users).Exists)
./test.go:22: Users.Exists undefined (type Users has no method Exists)
注意,在這個人為的例子中,驗證用戶的存在是沒有意義的。 但是,要點是,如果確實有一些重要的內容需要驗證,則數據庫函數應該具有調用某些其他數據庫函數的能力。
我如何才能解決這個問題?
(編輯-為清晰起見,修改了代碼段。)
您想做的事在Go中是不可能的。 Users.Exists
是一個方法表達式 。 有了這些,您可以采用一種方法並將其轉換為簡單的函數類型。
userExists := Users.Exists
user := User{}
// now userExists can be called as a regular function with
// first argument of a Users type
exists := userExists(&user, id)
結果,您無法像上面提到的那樣完全構建模型。
Go並不是一種完全面向對象的語言,因此您不應嘗試在其中嚴格復制OOP結構和習慣用語。 在上述情況下,如果需要Exists
函數,則可以始終將Users
移到單獨的程序包中,並將Exists
定義為函數:
package user
type Users struct {}
// other methods on Users type
func Exists(id int) bool {
// check to see if user exists
}
您現在可以撥打以下電話:
import "user"
user.Exists(id)
初始化結構后,可以使用自我引用填充它。 由於我是Go語言的新手,所以我不確定它是否是慣用語言,但似乎還可以。
固定代碼段:包主
import "fmt"
// A model that contains all of the structs for our database tables
type Model struct {
Users
Purchases
}
// A struct for functions that have to do with the "users" table
type Users struct {
db *Model
}
func (self *Users) Exists(id int) bool {
// Check to see if the user exists
// SELECT id FROM users WHERE id = ?
return true // (omitted)
}
// A struct for functions that have to do with the "purchases" table
type Purchases struct {
db *Model
}
func (self *Purchases) Count(id int) int {
// First validate that the user exists
if self.db.Users.Exists(id) == false { // This succeeds now <--------------
return 0
} else {
// Get the count of that user's purchases
// SELECT COUNT(user_id) FROM purchases WHERE user_id = ?
return 50 // (omitted)
}
}
func main() {
// Initialize the model and fill it with helpful self-references
db := Model{}
db.Users.db = &db
db.Purchases.db = &db
// In practice, you will want to do this in some sort of custom constructor, like:
// var db Model*
// db := Model.NewModel(db)
numPurchases := db.Purchases.Count(123)
if numPurchases != 0 {
fmt.Println("User #123 has", numPurchases, "purchases!")
} else {
fmt.Println("User #123 does not exist!")
}
}
如果需要在Users struct
字段,則可以使用db.Exists(2)
甚至Users.Exists(db, 2)
都有效。 像這樣的工作示例代碼:
package main
import "fmt"
type Users struct {
Ids []int
}
func (t Users) Exists(id int) bool {
for _, v := range t.Ids {
if v == id {
return true
}
}
return false
}
func main() {
db := Users{[]int{1, 2}}
r1 := db.Exists(2)
r2 := Users.Exists(db, 2)
fmt.Println(r1, r2) // true true
}
您可以像db.Exists(2)
甚至是Users.Exists(db, 2)
一樣使用它
兩者都是有效的。 您可以將Users struct
僅用於分組方法,例如以下工作示例代碼:
package main
import "fmt"
type Users struct{}
var Ids = []int{1, 2}
func (t Users) Exists(id int) bool {
for _, v := range Ids {
if v == id {
return true
}
}
return false
}
func main() {
db := Users{}
r1 := db.Exists(2)
r2 := Users.Exists(db, 2)
fmt.Println(r1, r2) // true true
}
您不需要分組時可以使用UserExists(2)
,例如以下工作示例代碼:
package main
import "fmt"
type Users struct{}
var Ids = []int{1, 2}
func UserExists(id int) bool {
for _, v := range Ids {
if v == id {
return true
}
}
return false
}
func main() {
r1 := UserExists(2)
fmt.Println(r1) // true
}
因此,在您的情況下,這可以正常工作:
package main
import "fmt"
type Model struct {
Users
Purchases
}
type Users struct{}
var users Users
func (*Users) Exists(id int) bool {
return true
}
type Purchases struct{}
func (*Purchases) Count(id int) int {
if users.Exists(id) == false {
return 0
} else {
return 50
}
}
func main() {
db := Model{}
numPurchases := db.Purchases.Count(123)
if numPurchases != 0 {
fmt.Println("User #123 has", numPurchases, "purchases!")
}
}
輸出:
User #123 has 50 purchases!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.