
# 具体步骤
1. 获取连接参数所需变量值，并拼接创建数据库连接所需连接串。
   
   ![](https://support.huaweicloud.com/bestpractice-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
   - 连接串支持DSN和URL两种格式。
   
   - 数据库连接参数参考《开发指南》中"应用程序开发教程 \> 基于Go驱动开发 \> 开发步骤 \> 连接数据库"章节。
   
   
   [具体步骤](https://support.huaweicloud.com/bestpractice-gaussdb/gaussdb-23-0144.html#ZH-CN_TOPIC_0000002633580704)涉及的参数变量值可通过[前置准备](https://support.huaweicloud.com/bestpractice-gaussdb/gaussdb-23-0141.html#ZH-CN_TOPIC_0000002663779937)中设置的环境变量获取值，并进行拼接，如以下代码所示。连接参数的值不局限于通过os.Getenv获取环境变量中的值获取，也可通过读取配置文件、写固定值等方式进行设置。
   ```
   hostip := os.Getenv("GOHOSTIP")                   // GOHOSTIP：写入环境变量的IP地址
   port := os.Getenv("GOPORT")                       // GOPORT：写入环境变量的port
   usrname := os.Getenv("GOUSRNAME")                 // GOUSRNAME：写入环境变量的用户名
   passwd := os.Getenv("GOPASSWD")                   // GOPASSWD：写入环境变量的用户密码
   dbname := os.Getenv("GODBNAME")                   // GODBNAME：写入环境变量的目标连接数据库名
   connect_timeout := os.Getenv("GOCONNECT_TIMEOUT") // GOCONNECT_TIMEOUT：写入环境变量的连接数据库超时时间
   socket_timeout := os.Getenv("GOSOCKET_TIMEOUT")   // GOSOCKET_TIMEOUT：写入环境变量的SQL最长的执行时间
   rootcertPath := os.Getenv("GOROOTCERT")           // GOROOTCERT：写入环境变量的根证书路径
   sslkeyPath := os.Getenv("GOSSLKEY")               // GOSSLKEY：写入环境变量的客户端证书的密钥路径
   sslcertPath := os.Getenv("GOSSLCERT")             // GOSSLCERT：写入环境变量的客户端SSL证书路径
   sslmode := os.Getenv("GOSSLMODE")                 // GOSSLMODE：写入环境变量的启用SSL加密的方式
   ```
   - 以DSN连接串为例，赋值给变量"dsn"，DSN推荐连接参数以及格式参考如下：
     ```
     dsn := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s connect_timeout=%s socketTimeout=%s sslmode=%s sslrootcert=%s sslkey=%s sslcert=%s target_session_attrs=master",
      hostip,
      port,
      usrname,
      passwd,
      dbname,
      connect_timeout,
      socket_timeout,
      sslmode,
      rootcertPath,
      sslkeyPath,
      sslcertPath,
     )
     ```
     
   
   - 以URL连接串为例，赋值给变量"url"，推荐连接参数以及URL格式参考如下：
     ```
     url := fmt.Sprintf("gaussdb://%s:%s@%s:%s/%s?connect_timeout=%s&socketTimeout=%s&sslmode=%s&sslrootcert=%s&sslkey=%s&sslcert=%s&target_session_attrs=master",
      usrname,
      passwd,
      hostip,
      port,
      dbname,
      connect_timeout,
      socket_timeout,
      sslmode,
      rootcertPath,
      sslkeyPath,
      sslcertPath,
     )
     ```
     
   
   
   ![](https://support.huaweicloud.com/bestpractice-gaussdb/public_sys-resources/note_3.0-zh-cn.png)
   - connect_timeout：该参数用于设置连接服务器操作的超时值，单位：秒。超时时间根据实际网络情况设置，默认为0，即不会超时。
   
   - socket_timeout：该参数用于设置限制单SQL最长的执行时间，单语句执行超过该值则会中断重连。建议根据业务特征进行配置，如果未配置，默认为0，即不会超时。
   
   - sslmode：该参数用于设置启用SSL加密的方式。
   
   - target_session_attrs：指定数据库的连接类型，该参数用于识别主备节点，默认值为any。
    
   
   
2. 通过[1]中拼接的连接串创建数据库连接对象。
   
   Golang的database/sql标准库提供了sql.Open接口执行创建数据库连接对象，并返回数据库连接对象以及错误信息。
   ```
   func Open(driverName, dataSourceName string) (*DB, error)
   ```
   - DSN连接串场景：
     ```
     db, err := sql.Open("gaussdb", dsn)
     ```
     
   
   
   
   - URL连接串场景：
     ```
     db, err := sql.Open("gaussdb", url)
     ```
     
   
   
   
   
3. 通过[2]创建的数据库连接对象创建事务对象。
   
   数据库连接对象提供了Begin接口执行创建事务对象，并返回事务对象以及错误信息。
   ```
   func (db *DB) Begin() (*Tx, error)
   ```
   以下为创建事务对象，并以变量"tx"进行接收返回的事务对象。
   ```
   tx, err := db.Begin()
   ```
   
   
4. 通过[3]中创建的事务对象执行批量插入。
   
   以Exec接口为例，具体参考《开发指南》中"应用程序开发教程 \> 基于Go驱动开发 \> Go接口参考 \> type Tx"章节。
   ```
   (tx *Tx)Exec(query string, args ...interface{})
   ```
   通过[3]中创建的事务对象"tx"，调用Exec接口批量插入employee表为例，其中包括拼接批量插入SQL以及传入批量插入所需的值，数据量根据用户实际为准。
   ```
   employee := []struct {
    Name string
    Age  uint8
   }{{Name: "zhangsan", Age: 21}, {Name: "lisi", Age: 22}, {Name: "zhaowu", Age: 23}}
   batchSql := "INSERT INTO employee (name, age) VALUES "
   vals := []interface{}{}
   placeholders := ""
   for i, u := range employee {
    placeholders += "(?, ?)"
    if i < len(employee)-1 {
     placeholders += ","
    }
    vals = append(vals, u.Name, u.Age)
   }
   stmt := batchSql + placeholders
   result, err := tx.Exec(stmt, vals...)
   ```
   
   
5. 【可选】通过[3]中创建的事务对象进行回滚事务。
   
   事务对象提供了Rollback接口进行回滚事务。
   ```
   func (tx *Tx) Rollback() error
   ```
   当事务中出错时，可以通过调用[3]中创建的事务对象"tx"的Rollback接口进行回滚事务。
   ```
   tx.Rollback()
   ```
   
   
6. 通过[3]中创建的事务对象提交事务。
   
   事务对象提供了Commit接口进行提交事务。
   ```
   func (tx *Tx) Commit() error
   ```
   通过[3]中创建的事务对象"tx"的Commit接口进行提交事务。
   ```
   err := tx.Commit()
   ```
   
   
7. 【可选】通过[2]创建的数据库连接对象执行查询。
   
   数据库对象和事务对象均提供了查询接口，参考《开发指南》中"应用程序开发教程 \> 基于Go驱动开发 \> Go接口参考"章节下"type DB"章节和"type Tx"章节中提供的查询接口。
   以调用[2]中创建的数据库对象"db"提供的Query接口为例，查询[4]批量插入的结果，并通过变量"rows"接收查询结果对象。
   ```
   rows, err := db.Query("SELECT id, name, created_at FROM users;"
   ```
   
   
8. 【可选】通过[7]获取的结果对象获取结果集列数和列名列表。
   
   [7]中结果对象为Golang的database/sql中的Rows类型，该类型提供了Columns接口来返回查询结果集列名的列表，参考《开发指南》中"应用程序开发教程 \> 基于Go驱动开发 \> Go接口参考 \> type Rows"章节。
   ```
   func (rs *Rows) Columns() ([]string, error)
   ```
   以调用[7]中获取的查询结果对象提供的接口Columns获取查询到的列名列表，并赋值到变量"columns"中为例：
   ```
   columns, err := rows.Columns()
   ```
   结果集的列数可以通过len函数计算"columns"个数获取。
   ```
   len(columns)
   ```
   
   
9. 【可选】通过[7]获取的结果对象获取结果集列的类型等元信息。
   
   [7]中结果对象为Golang的database/sql中的Rows类型，该类型提供了ColumnTypes接口来返回查询结果集列名的列表，参考《开发指南》中"应用程序开发教程 \> 基于Go驱动开发 \> Go接口参考 \> type Rows"章节。
   ```
   func (rs *Rows) ColumnTypes() ([]*ColumnType, error)
   ```
   通过[7]中获取的查询结果获取列信息。
   以调用[7]中获取的查询结果对象提供的接口ColumnTypes获取查询到的列类型对象列表\[\]\*ColumnType，并赋值到变量"columnTypes"中为例：
   ```
   columnTypes, err := rows.ColumnTypes()
   ```
   应用代码可以通过遍历列类型对象列表"columnTypes"获取返回结果列的类型信息。
   type ColumnType提供以下接口描述数据库表中的列类型信息：
   表1type ColumnType接口的常用方法 
   | **方法**                              | **描述**                                       | **返回值** **类型**                     |
   |:---|:---|:---|
   | (ci \*ColumnType)DatabaseTypeName() | 返回列类型的数据库系统名称。返回空字符串表示该驱动类型名字并未被支持。          | error                              |
   | (ci \*ColumnType)DecimalSize()      | 返回小数类型的范围和精度。返回值ok的值为false时，说明给定的类型不可用或者不支持。 | precision, scale int64, ok boolean |
   | (ci \*ColumnType)Length()           | 返回数据列类型长度。返回值ok的值为false时，说明给定的类型是非可变长度。      | length int64, ok boolean           |
   | (ci \*ColumnType)ScanType()         | 返回一种Go类型，该类型能够在Rows.scan进行扫描时使用。             | reflect.Type                       |
   | (ci \*ColumnType)Name()             | 返回数据列的名字。                                    | string                             |
      
   
   
10. 通过[2]创建的数据库连接对象执行关闭连接。
    
    数据库连接对象提供了Close接口进行数据库连接的关闭。
    ```
    func (db *DB) Close() error
    ```
    执行以下语句关闭[2]创建的数据库连接对象。
    ```
    db.Close()
    ```
    
    
 
