2016-07-22 19 views
0

我正在清理Go/Golang項目中的代碼。我想,這可能是習慣,以創建一個面向對象的方式的模型,這樣我可以做,例如:如何從Go/Golang的另一個方法表達式中訪問方法表達式(結構函數)?

  • db.Users.GetID("john")(做的事,在「用戶」表)
  • 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) 

請注意,在這個人爲的例子中,它是點ss來驗證用戶是否存在。然而,重點在於DB功能應該有能力調用其他DB功能,以防有些事情需要驗證。

我該如何完成/解決此問題?

(編輯 - 修改爲清楚起見,代碼段。)

回答

0

初始化該結構後,可以使用自引用來填充它。由於我是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!") 
    } 
} 
1

你正在嘗試做的圍棋是不可能的。 Users.ExistsMethod Expression。有了這些,你可以採取一種方法並將其轉換爲簡單的函數類型。

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

嗯,我確實設法解決了這個問題,所以我不會那麼快地說這是不可能的。 ;)(看我發佈的答案。) – James

+0

你可以給一個在線工作的例子嗎?你的代碼不能編譯:https://play.golang.org/p/UHmDB39Xxv 另外,說'self.db.Users.Exists(1)'等同於說'user.Exists(id)'在很多更人爲和難以辨認的方式。無論如何,你現在將如何構建一個實際的用戶對象?它現在是不同的類型,導致兩種不同的用戶類型? – abhink

+0

我的歉意。我已經更新了問題代碼和我的回覆代碼,使一切變得更加清晰。它現在也應該編譯。 – James

0

,如果你需要內部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! 
相關問題