3 回答
TA贡献1816条经验 获得超4个赞
在函数中使用database
而不是interface{}
cacheNew
func cacheNew(dbdriver database) cache {
postgres
没有实现database
,因为GetUser
方法有指针接收器。因此,将postgres
类型变量的地址发送到cacheNew
dbViaCache := cacheNew(&db)
TA贡献1772条经验 获得超6个赞
无论是基于意见的,我都不建议混合使用数据库和缓存功能。
我可以推荐以下内容:首先创建包cache,然后从接口开始cache.go:
// Cache is an interface which abstracts cache providers details for testability and usability
type Cache interface {
// Get retrieves the content associated with the given key. decoding it into the given
// pointer.
//
// Returns:
// - nil if the value was successfully retrieved and ptrValue set
// - ErrCacheMiss if the value was not found in the cache
// - an implementation specific error otherwise
Get(key string, ptrValue interface{}) error
// set the given key/value in the cache, overwriting any existing value
// associated with that key
Set(key string, ptrValue interface{}, expires time.Duration) error
}
然后你可以在这个包中创建文件,比如inmem.go,,redis.go实现这个接口的所有其他东西。然后,您可以准备 YAML 配置,指示您要使用的缓存提供程序,并在服务器启动期间对其进行实例化。
cache:
active: "redis"
redis:
address: "127.0.0.1:6379"
password: #
poolSize: #
对于数据库,一切都比较棘手。根据我的经验,一次选择数据库提供程序并使用jmoiron/sqlx甚至本机驱动程序会更容易,例如用于高负载处理程序的纯pgx 。由于缺乏泛型和相对较慢的反射,除了基本的 CRUD 之外,大多数情况下对数据库提供者的抽象是不切实际的。对于非常简单的情况,您可以模仿存储库模式
type UserRepository interface {
Get(ctx context.Context, id uint64) (*User, error)
}
type userRepository struct {
db *sqlx.DB
}
func (r *userRepository) Get(ctx context.Context, id uint64) (*User, error) {
const query = `SELECT id, email, login, language_id FROM users WHERE id = $1`
user := &User{}
if err := r.db.GetContext(ctx, user, query, id); err != nil {
return nil, err
}
return user, nil
}
然后在您的服务中,您将拥有类似的东西
key := "app:users#23"
user := &User{}
if err := svc.cache.Get(key, user); err != nil {
user, err = svc.userRepo.Get(userID)
if err != nil {
// handle
}
// otherwise, set cache
go svc.cache.Set(key, user, time.Minutes * 15)
}
// perform other actions with user
希望能帮助到你!
TA贡献2012条经验 获得超12个赞
为了解决您的问题,添加 newPostgres 构造函数。下面我对您的初始代码进行了更正。
package main
import "fmt"
type database interface {
GetUser(string)
}
type postgres struct {
hostname string
}
func newPostgres(hostname string) *postgres {
return &postgres{
hostname: hostname,
}
}
func (p *postgres) GetUser(u string) {
fmt.Printf("Postgres: GetUser %s\n", u)
}
type cache struct {
db database
}
func cacheNew(db database) cache {
return cache{
db: db,
}
}
func (c *cache) GetUser(u string) {
fmt.Printf("Cache: GetUser %s\n", u)
c.db.GetUser(u)
}
func main() {
db := newPostgres("x")
db.GetUser("joe")
dbViaCache := cacheNew(db)
dbViaCache.GetUser("joe")
}
- 3 回答
- 0 关注
- 104 浏览
添加回答
举报