[golang] 接收 interface 返回 struct
source link: https://wayou.github.io/2021/09/11/_golang__%E6%8E%A5%E6%94%B6_interface_%E8%BF%94%E5%9B%9E_struct/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
[golang] 接收 interface 返回 struct
2021 9 月 11 日
[golang] 接收 interface 返回 struct
Golang 编程中有个最佳实践是将依赖定义为 interface 而返回定义为 struct。
interface in
这里包含两层意思,
- 依赖定义成 interface
- 这个 interface 应该在调用方定义
因为 interface 是 duck typing 的,只要满足 interface 定义的约束就可作为入参,这有助于将调用方与被调用方解耦。
具体来说,比如有个用于创建查询用户信息的服务:
//user.go
package user
type UserStore interface {
Insert(item interface{}) error
Get(id int) error
}
type UserService struct {
store UserStore
}
// Accepting interface here!
func NewUserService(s UserStore) *UserService {
return &UserService{
store: s,
}
}
func (u *UserService) CreateUser() { ... }
func (u *UserService) RetrieveUser(id int) User { ... }
它不用关心底层具体使用哪种数据库,以及使用什么方法进行插入,它只约定依赖于一个 UserStore
接口。
同时创建一个实现了该接口方法的模块:
// store/mysql.go
package store
import "database/sql"//db.go
package db
type Store struct {
db *sql.DB
}
func NewDB() *Store { ... } //func to initialise DB
func (s *Store) Insert(item interface{}) error { ... } //insert item
func (s *Store) Get(id int) error { ... } //get item by id
type MySQLStore struct {
db *sql.DB
}
func (s *MySQLStore) Insert(item interface{}) error {
return nil
}
因为 user service 依赖的是 interface,当后面我们切换数据库到其他数据库比如 PostgreSQL 时,只需要新建一个 store 提供对应方法即可,而不用更新我们的 user service 去接收一个叫作 PGStore
的依赖。
同理,编写单元测试也会方便许多,我们只需要 mock 一个实现了该接口的对象即可,因为 interface 的依赖已经通过抽象剥离了出来,使得测试变得方便和纯粹。
注意到调用方所依赖的 interface 是在 UserService
中定义的,一是因为调用方比较清楚它的依赖,二是同样达到解耦的目的,如果定义在被调方,则会形成入侵。
struct out
而我们函数的返回应该是 struct 类型。这样在调用后得到提具体的类型,上面的字段是清晰的,不用再次作类型转换。
但有个例外是函数返回的错误对象,是使用 error
这个 interface 来接收的。因为不同地方返回的错误实现可能不同,大部分情况下会是自定义的错误对象,只有使用 interface 来进行接收。
Recommend
-
68
emacs-go-tag Introduction Edit field tags for golang struct fields, based on gomodifytags. This package is inspired by GoAddTags of
-
58
写代码时碰到这么一个需求,某个字段根据不同条件对应不同子结构体,通过interface返给前端,同时前端上传时也要通过这个字段将数据传给后端。 struct -> json这个比较好办,给interface赋值不同的子结构体即可。json -> str...
-
11
在 上一篇
-
24
使用 Go 已经一年,深深沉浸在其简洁的设计中,就像其官网描述的: Go is expressive, concise, clean, and efficient. It’s a fast, statically typed, compiled language that feels like a dynamically typed, interpreted...
-
26
使用 Go 已经一年,深深沉浸在其简洁的设计中,就像其官网描述的: Go is expressive, concise, clean, and efficient. It’s a fast, statically typed, compiled language that feels like a dynamically typed, interpreted language.
-
5
在 Go 语言中,一个 struct 实现了某个接口里的所有方法,就叫做这个 struct 实现了该接口。 下面写一个 Demo 实现一下,先写一个 Study interface{},里面需要实现 4 个方法 Listen、Speak、Read、Write,然后再写一个 study struct{},...
-
9
Golang 用interface{} map 给struct赋值 siskinc · 2019-02-16 08:34:43 · 2841 次点击 · 预计阅读时间 1 分钟 · 大约8小时之前 开始浏览 ...
-
5
V2EX › Java 服务层到底接收和返回什么对象。服务层的中转对象应该是什么 O? golangLover...
-
4
GO 语言接口与结构体 - interface & struct 坚果jimbowhy · 2019-08-02 22:32:40 · 4826 次点击 · 预计阅读时间 3 分钟 · 大约8小时之前 开始浏览 ...
-
5
go 使用 vscode 开发时,函数用 ctrl+f12 转到实现时仅跳转到 interface,如何确定是哪个 struct 实现的方法呢? V2EX › Go 编程语言
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK