---
sidebar_position: 4
---

# Go Connector

## 安装准备

Go 连接器支持的系统有：

| **CPU 类型** | x64（64bit） |          |          | aarch64  | aarch32    |
| ------------ | ------------ | -------- | -------- | -------- | ---------- |
| **OS 类型**  | Linux        | Win64    | Win32    | Linux    | Linux      |
| **支持与否** | **支持**     | **支持** | **支持** | **支持** | **开发中** |

安装前准备：已安装好 TDengine 应用驱动，参考[安装连接器驱动步骤](/reference/connector)。

## 示例程序

使用 Go 连接器的示例代码请参考 `https://github.com/taosdata/TDengine/tree/develop/examples/go` 以及[视频教程](https://www.taosdata.com/blog/2020/11/11/1951.html)。

示例程序源码也位于安装目录下的 examples/go/taosdemo.go 文件中。

:::tip
建议 Go 版本是 1.13 及以上，并开启模块支持：
:::

```sh
go env -w GO111MODULE=on
go env -w GOPROXY=https://goproxy.io,direct
```

在 taosdemo.go 所在目录下进行编译和执行：

```sh
go mod init taosdemo
go get github.com/taosdata/driver-go/taosSql
# use win branch in Windows platform.
#go get github.com/taosdata/driver-go/taosSql@win
go build
./taosdemo -h fqdn -p serverPort
```

## Go 连接器的使用

TDengine 提供了 GO 驱动程序包`taosSql`。`taosSql` 实现了 GO 语言的内置接口 `database/sql/driver`。用户只需按如下方式引入包就可以在应用程序中访问 TDengine。

```go
import (
  "database/sql"
  _ "github.com/taosdata/driver-go/v2/taosSql"
)
```

:::tip
下划线与双引号之间必须有一个空格。

:::

`taosSql` 的 v2 版本进行了重构，分离出内置数据库操作接口 `database/sql/driver` 到目录 `taosSql`；订阅、 stmt 等其他功能放到目录 `af`。

## 常用 API

- `sql.Open(DRIVER_NAME string, dataSourceName string) *DB`

  该 API 用来打开 DB，返回一个类型为\*DB 的对象，一般情况下，DRIVER_NAME 设置为字符串 `taosSql`，dataSourceName 设置为字符串 `user:password@/tcp(host:port)/dbname`，如果客户想要用多个 goroutine 并发访问 TDengine, 那么需要在各个 goroutine 中分别创建一个 sql.Open 对象并用之访问 TDengine。

  **注意**： 该 API 成功创建的时候，并没有做权限等检查，只有在真正执行 Query 或者 Exec 的时候才能真正的去创建连接，并同时检查 user/password/host/port 是不是合法。另外，由于整个驱动程序大部分实现都下沉到 taosSql 所依赖的 libtaos 动态库中。所以，sql.Open 本身特别轻量。

- `func (db *DB) Exec(query string, args ...interface{}) (Result, error)`

sql.Open 内置的方法，用来执行非查询相关 SQL

- `func (db *DB) Query(query string, args ...interface{}) (*Rows, error)`

sql.Open 内置的方法，用来执行查询语句

- `func (db *DB) Prepare(query string) (*Stmt, error)`

  sql.Open 内置的方法，Prepare creates a prepared statement for later queries or executions.

- `func (s *Stmt) Exec(args ...interface{}) (Result, error)`

  sql.Open 内置的方法，executes a prepared statement with the given arguments and returns a Result summarizing the effect of the statement.

- `func (s *Stmt) Query(args ...interface{}) (*Rows, error)`

  sql.Open 内置的方法，Query executes a prepared query statement with the given arguments and returns the query results as a \*Rows.

- `func (s *Stmt) Close() error`

  sql.Open 内置的方法，Close closes the statement.

## 其他代码示例

[Consume Messages from Kafka](https://github.com/taosdata/go-demo-kafka) 是一个通过 Go 语言实现消费 Kafka 队列写入 TDengine 的示例程序，也可以作为通过 Go 连接 TDengine 的写法参考。

## Go RESTful 的使用

### 引入

```go restful
import (
  "database/sql"
  _ "github.com/taosdata/driver-go/v2/taosRestful"
)
```

`go.mod ` 的文件 require 块使用  github.com/taosdata/driver-go/v2 develop  之后执行  `go mod tidy `

`sql.Open `的 driverName 为  `taosRestful`

### DSN

格式为：

数据库用户名:数据库密码@连接方式(域名或 ip:端口)/[数据库][?参数]

样例：

`root:taosdata@http(localhost:6041)/test?readBufferSize=52428800`

参数：

`disableCompression` 是否接受压缩数据，默认为 true 不接受压缩数据，如果传输数据使用 gzip 压缩设置为 false。

`readBufferSize` 读取数据的缓存区大小默认为 4K(4096)，当查询结果数据量多时可以适当调大该值。

### 使用限制

由于 RESTful 接口无状态所以 `use db` 语法不会生效，需要将 db 名称放到 SQL 语句中，如：`create table if not exists tb1 (ts timestamp, a int)`改为`create table if not exists test.tb1 (ts timestamp, a int)`否则将报错`[0x217] Database not specified or available`。

也可以将 db 名称放到 DSN 中，将 `root:taosdata@http(localhost:6041)/` 改为 `root:taosdata@http(localhost:6041)/test`，此方法在 TDengine 2.4.0.5 版本的 taosAdapter 开始支持。当指定的 db 不存在时执行 `create database` 语句不会报错，而执行针对该 db 的其他查询或写入操作会报错。完整示例如下：

```go restful demo
package main

import (
    "database/sql"
    "fmt"
    "time"

    _ "github.com/taosdata/driver-go/v2/taosRestful"
)

func main() {
    var taosDSN = "root:taosdata@http(localhost:6041)/test"
    taos, err := sql.Open("taosRestful", taosDSN)
    if err != nil {
        fmt.Println("failed to connect TDengine, err:", err)
        return
    }
    defer taos.Close()
    taos.Exec("create database if not exists test")
    taos.Exec("create table if not exists tb1 (ts timestamp, a int)")
    _, err = taos.Exec("insert into tb1 values(now, 0)(now+1s,1)(now+2s,2)(now+3s,3)")
    if err != nil {
        fmt.Println("failed to insert, err:", err)
        return
    }
    rows, err := taos.Query("select * from tb1")
    if err != nil {
        fmt.Println("failed to select from table, err:", err)
        return
    }

    defer rows.Close()
    for rows.Next() {
        var r struct {
            ts time.Time
            a  int
        }
        err := rows.Scan(&r.ts, &r.a)
        if err != nil {
            fmt.Println("scan error:\n", err)
            return
        }
        fmt.Println(r.ts, r.a)
    }
}
```

### 常见问题

- 无法找到包`github.com/taosdata/driver-go/v2/taosRestful`

  将 `go.mod` 中 require 块对`github.com/taosdata/driver-go/v2`的引用改为`github.com/taosdata/driver-go/v2 develop`，之后执行 `go mod tidy`。

- stmt 相关接口崩溃

  RESTful 不支持 stmt 相关接口，建议使用`db.Exec`和`db.Query`。

- 使用 `use db` 语句后执行其他语句报错 `[0x217] Database not specified or available`

  在 RESTful 接口中 SQL 语句的执行无上下文关联，使用 `use db` 语句不会生效，解决办法见上方使用限制章节。

- 使用 taosSql 不报错使用 taosRestful 报错 `[0x217] Database not specified or available`

  因为 RESTful 接口无状态，使用 `use db` 语句不会生效，解决办法见上方使用限制章节。

- 升级 `github.com/taosdata/driver-go/v2/taosRestful`

  将 `go.mod` 文件中对 `github.com/taosdata/driver-go/v2` 的引用改为 `github.com/taosdata/driver-go/v2 develop`，之后执行 `go mod tidy`。

- readBufferSize 参数调大后无明显效果

  readBufferSize 调大后会减少获取结果时 syscall 的调用。如果查询结果的数据量不大，修改该参数不会带来明显提升，如果该参数修改过大，瓶颈会在解析 JSON 数据。如果需要优化查询速度，需要根据实际情况调整该值来达到查询效果最优。

- disableCompression 参数设置为 false 时查询效率降低

  当 disableCompression 参数设置为 false 时查询结果会 gzip 压缩后传输，拿到数据后要先进行 gzip 解压。
