Dalam Go, mengejek fungsi yang diisytiharkan pada jenis konkrit, seperti func F() {} dan func (T) M() {}, tidak mungkin. Walau bagaimanapun, terdapat pendekatan lain untuk mencapai kefungsian yang serupa.
Go membenarkan nilai fungsi mengejek, tidak kira sama ada ia disimpan dalam pembolehubah, sebagai medan pada struct, atau sebagai parameter dihantar ke fungsi lain. Sebagai contoh, pertimbangkan perkara berikut:
var Fn = func() { ... } type S struct { Fn func() } func F(Fn func())
Dalam ketiga-tiga kes, Fn boleh dipermainkan.
Pendekatan yang lebih disukai untuk mengejek dalam Go ialah menggunakan antara muka. Contohnya:
type ProductRepository interface { GetProductById(DB *sql.DB, ID int) (p Product, err error) } // The real implementer type ProductStore struct{} func (ProductStore) GetProductById(DB *sql.DB, ID int) (p Product, err error) { q := "SELECT * FROM product WHERE id = ?" // ... } // The mock implementer type ProductRepositoryMock struct{} func (ProductRepositoryMock) GetProductById(DB *sql.DB, ID int) (p Product, err error) { // ... }
Sebarang kod yang bergantung pada ProductRepository kini boleh menggunakan ProductStore dalam senario biasa dan ProductRepositoryMock semasa ujian.
Satu lagi pilihan untuk mengejek yang membolehkan untuk mengekalkan pengisytiharan fungsi sedia ada anda adalah untuk menentukan antara muka yang meniru kaedah *sql.DB dan gunakannya sebaliknya. Contohnya:
type DBIface interface { Query(query string, args ...interface{}) (*sql.Rows, error) // Only declare methods that are actually used. } type DBMock struct{} func (DBMock) Query(query string, args ...interface{}) (*sql.Rows, error) { // ... } func GetProductByName(DB DBIface, name string) (p Product, err error) { ... }
Dengan pendekatan ini, parameter DB untuk GetProductByName menjadi boleh dipermainkan.
Atas ialah kandungan terperinci Bagaimanakah Saya Boleh Mengejek Fungsi dengan Berkesan dalam Go?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!