Starting with this article, let’s take a look at the components and development practices that Go-Zero requires to develop a project.

Let’s start with the Model layer and talk about the GO-Zero API and packaging details. First of all, apis connected to the Model layer focus on core/ Stores. We first look at the operation of mysql such database, API method we came to core/stores/ SQLX, so the next few articles with a general introduction to the use of SQLX and design ideas.

Quick to use

func main(a) {
  / / 1
  const datasource = "user:password@/dbname"
  mysqlDB := sqlx.NewMysql(datasource)
  / / 2
  um := model.NewUserModel(mysqlDB,"User")
  / / 3
  ul := logic.NewUserLogic(um)
  / / 4
  engine.AddRoutes(nginxApi(ul))
  engine.Start()
}

// NewUserModel, NewUserLogic is similar
func NewUserModel(conn sqlx.SqlConn, table string) *UserModel {
	return &UserModel{conn: conn, table: table}
}

// nginxApi injects logic into Handle and binds routing and handler
func nginxApi(ul *logic.UserLogic) []rest.Route {
	return []rest.Route{
		{
			Method:  http.MethodGet,
			Path:    "/user/:id".// /user/54er6;
			Handler: handler.NewUserHandler(ul).GetUserById,
    }
}
Copy the code

To sum up:

  1. NewMysqlCreating a database connection
  2. Create the correspondingmodelAnd pass the connection to the correspondingNewModelIt needs to be written by developers.”
  3. modelIt’s for the next level uplogicTo provide services
  4. willlogicInjected into thehandler, at the same timehandlerBinding to routes is enabledServer

This gives us the simplest structure for model-logic-handler. Then let’s look at how data is manipulated in the Model layer:

var userBuilderQueryRows = strings.Join(builderx.FieldNames(&User{}), ",")

type User struct {
  Avatar string `db:"avatar"` / / avatar
  UserName string `db:"user_name"` / / name
  Sex int `db:"sex"` // 1 male,2 female
  MobilePhone string `db:"mobile_phone"` / / cell phone number
}

func (um *UserModel) Insert(user *User) (int64, error) {
  const insertsql = `insert into `+um.table+` (`+userBuilderQueryRows+`) values(? ,? ,?) `
  // insert "delete using the same way"
  res, err := um.conn.Exec(insertsql, user.Avatar, user.UserName, user.Sex, user.MobilePhone)
  iferr ! =nil {
    logx.Errorf("insert User Position Model Model err, err=%v", err)
    return - 1, err
  }
  id, err := res.LastInsertId()
	iferr ! =nil {
		logx.Errorf("insert User Model to Id parse id err,err=%v", err)
		return - 1, err
	}
	return id, nil
}

func (um *UserModel) FindOne(uid int64) (*User, error) {
  var user User
  // query
  const querysql = `select `+userBuilderQueryRows+` from `+um.table+` where id=? limit 1`
	err := um.conn.QueryRow(&user, querysql, uid)
	iferr ! =nil {
		logx.Errorf("userModile.findOne error ,id=%d,err=%s", uid, err.Error())
		if err == sqlx.ErrNotFound {
			return nil, ErrNotFound
		}
		return nil, err
	}
	return &user, nil
}
Copy the code
  • insert/update/delete:conn.Exec(insertsql/updatesql/deletesql, args...)
  • query:conn.QueryRow(&model, querysql, args...)

This is the simplest CRUD structure: first build the Model, then manipulate the model to operate.

The code structure

The file name role
bulkinserter.go Bulk insert
mysql.go NewMysql
orm.go Parsing, serializationmodelThe operation of the
sqlconn.go abstractcrudInterface for operation
tx.go The transaction operations

From sqlconn.go interinterface relationship:

CommonSqlConn and txSession are where the real implementation is. Let’s start with an overview of API functions:

API parameter role
Exec(query, args…) SQL, SQL parameter insert/update/delete
Prepare(query) sql Precompiled SQL
QueryRow(&model, query, args…) Model, SQL, SQL parameters Query a row of data and assign it to “model”
QueryRowPartial(&model, query, args…) Model, SQL, SQL parameters Select Partial columns from model
QueryRows/QueryRowsPartial Same as above Query the multi-line API
Transact(func(session Session) error) The transaction operations By wrapping the operations in the parameters in transactions, the developer can only focus on writing the functions in the parameters

conclusion

Go-zero’S SQLX shields go’s native SQL operations. Developers only need to focus on SQL compilation and data objects encapsulated by services. There is no need to manually prepare and Scan data when assigning data as in native development.

This section gives you a brief overview of the interrelationships between interfaces and the apis that developers usually focus on. The next section will focus on how Go-Zero can help you assign data and prevent traffic from directly killing your database in the event of a large number of concurrent requests.

reference

  • go-zero sqlx
  • Go database/sql tutorial

Welcome to Go-Zero

Project address: github.com/tal-tech/go…

If you like the article, please click on github star 🤝