From 97c2b69b4d63d8e45b5bf17196eb0b309ab6fb73 Mon Sep 17 00:00:00 2001 From: andreyaksenov Date: Tue, 14 May 2024 16:31:16 +0300 Subject: [PATCH 1/4] Connectors: Go tutorial --- doc/how-to/getting_started_go.rst | 324 +++++++++++++------------ doc/how-to/getting_started_net_box.rst | 4 + 2 files changed, 169 insertions(+), 159 deletions(-) diff --git a/doc/how-to/getting_started_go.rst b/doc/how-to/getting_started_go.rst index 63b1169ba0..9c5bee060f 100644 --- a/doc/how-to/getting_started_go.rst +++ b/doc/how-to/getting_started_go.rst @@ -1,258 +1,264 @@ .. _getting_started-go: --------------------------------------------------------------------------------- Connecting from Go --------------------------------------------------------------------------------- +================== -.. _getting_started-go-pre-requisites: +**Examples on GitHub**: `sample_db `_, `go `_ -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Pre-requisites -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +The tutorial shows how to use the 2.x version of the `go-tarantool `__ library to create a Go application that connects to a remote Tarantool instance, performs CRUD operations, and executes a stored procedure. +You can find the full package documentation here: `Client in Go for Tarantool `__. -Before we proceed: -#. `Install `__ - the ``go-tarantool`` library. -#. :ref:`Start ` Tarantool (locally or in Docker) - and make sure that you have created and populated a database as we suggested - :ref:`earlier `: +.. _getting_started_go_sample_db: - .. code-block:: lua +Sample database configuration +----------------------------- - box.cfg{listen = 3301} - s = box.schema.space.create('tester') - s:format({ - {name = 'id', type = 'unsigned'}, - {name = 'band_name', type = 'string'}, - {name = 'year', type = 'unsigned'} - }) - s:create_index('primary', { - type = 'hash', - parts = {'id'} - }) - s:create_index('secondary', { - type = 'hash', - parts = {'band_name'} - }) - s:insert{1, 'Roxette', 1986} - s:insert{2, 'Scorpions', 2015} - s:insert{3, 'Ace of Base', 1993} +.. include:: getting_started_net_box.rst + :start-after: connectors_sample_db_config_start + :end-before: connectors_sample_db_config_end - .. IMPORTANT:: +.. _getting_started_go_sample_db_start: - Please do not close the terminal window - where Tarantool is running -- you'll need it soon. +Starting a sample database application +-------------------------------------- -#. In order to connect to Tarantool as an administrator, reset the password - for the ``admin`` user: +Before creating and starting a client Go application, you need to run the :ref:`sample_db ` application using ``tt start``: - .. code-block:: lua +.. code-block:: console - box.schema.user.passwd('pass') + $ tt start sample_db -.. _getting_started-go-connecting: +Now you can create a client Go application that makes requests to this database. -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Connecting to Tarantool -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -To get connected to the Tarantool server, write a simple Go program: +.. _getting_started_go_develop_client_app: -.. code-block:: go +Developing a client application +------------------------------- - package main +.. _getting_started_go_create_client_app: - import ( - "fmt" +Creating an application +~~~~~~~~~~~~~~~~~~~~~~~ - "github.com/tarantool/go-tarantool" - ) +1. Create the ``hello`` directory for your application and go to this directory: - func main() { + .. code-block:: console - conn, err := tarantool.Connect("127.0.0.1:3301", tarantool.Opts{ - User: "admin", - Pass: "pass", - }) + $ mkdir hello + $ cd hello - if err != nil { - log.Fatalf("Connection refused") - } +2. Initialize a new Go module: - defer conn.Close() + .. code-block:: console - // Your logic for interacting with the database - } + $ go mod init example/hello -The default user is ``guest``. +3. Inside the ``hello`` directory, create the ``hello.go`` file for application code. -.. _getting_started-go-manipulate: -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -Manipulating the data -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +.. _getting_started_go_import_: -.. _getting_started-go-insert: +Importing 'go-tarantool' +~~~~~~~~~~~~~~~~~~~~~~~~ -******************************************************************************** -Inserting data -******************************************************************************** +In the ``hello.go`` file, declare a ``main`` package and import the following packages: -To insert a :term:`tuple` into a :term:`space`, use ``Insert``: +.. literalinclude:: /code_snippets/snippets/connectors/go/hello.go + :language: go + :start-at: package main + :end-before: func main() + :dedent: -.. code-block:: go - resp, err = conn.Insert("tester", []interface{}{4, "ABBA", 1972}) +.. _getting_started_go_creating_connection: -This inserts the tuple ``(4, "ABBA", 1972)`` into a space named ``tester``. +Creating a connection +~~~~~~~~~~~~~~~~~~~~~ -The response code and data are available in the -`tarantool.Response `_ -structure: +1. Declare the ``main()`` function: -.. code-block:: go + .. code-block:: go - code := resp.Code - data := resp.Data + func main() { -.. _getting_started-go-query: + } -******************************************************************************** -Querying data -******************************************************************************** +2. Inside the ``main()`` function, add the following code: -To select a tuple from a space, use -`Select `_: + .. literalinclude:: /code_snippets/snippets/connectors/go/hello.go + :language: go + :start-after: func main() + :end-at: // Interacting with the database + :dedent: -.. code-block:: go + This code establishes a connection to a running Tarantool instance on behalf of ``sampleuser``. + The ``conn`` object can be used to make CRUD requests and execute stored procedures. - resp, err = conn.Select("tester", "primary", 0, 1, tarantool.IterEq, []interface{}{4}) -This selects a tuple by the primary key with ``offset = 0`` and ``limit = 1`` -from a space named ``tester`` (in our example, this is the index named ``primary``, -based on the ``id`` field of each tuple). -Next, select tuples by a secondary key. +.. _getting_started_go_using_data_operations: -.. code-block:: go +Using data operations +~~~~~~~~~~~~~~~~~~~~~ - resp, err = conn.Select("tester", "secondary", 0, 1, tarantool.IterEq, []interface{}{"ABBA"}) +.. _getting_started_go_inserting_data: -Finally, it would be nice to select all the tuples in a space. But there is no -one-liner for this in Go; you would need a script like -:ref:`this one `. +Inserting data +************** -For more examples, see https://github.com/tarantool/go-tarantool#usage +Add the following code to insert four tuples into the ``bands`` space: -.. _getting_started-go-update: +.. literalinclude:: /code_snippets/snippets/connectors/go/hello.go + :language: go + :start-at: // Insert data + :end-at: Inserted tuples: + :dedent: -******************************************************************************** -Updating data -******************************************************************************** +The ``NewInsertRequest()`` method creates an insert request object that is executed by the connection. -Update a :term:`field` value using ``Update``: -.. code-block:: go - resp, err = conn.Update("tester", "primary", []interface{}{4}, []interface{}{[]interface{}{"+", 2, 3}}) +.. _getting_started_go_querying_data: -This increases by 3 the value of field ``2`` in the tuple with ``id = 4``. -If a tuple with this ``id`` doesn't exist, Tarantool will return an error. +Querying data +************* -Now use ``Replace`` to totally replace the tuple that matches the -primary key. If a tuple with this primary key doesn't exist, Tarantool will -do nothing. +To get a tuple by the specified primary key value, use ``NewSelectRequest()`` to create an insert request object: -.. code-block:: go +.. literalinclude:: /code_snippets/snippets/connectors/go/hello.go + :language: go + :start-at: // Select by primary key + :end-at: Tuple selected the primary key value + :dedent: - resp, err = conn.Replace("tester", []interface{}{4, "New band", 2011}) +You can also get a tuple by the value of the specified index by using ``Index()``: -You can also update the data using ``Upsert`` that works similarly -to ``Update``, but creates a new tuple if the old one was not found. +.. literalinclude:: /code_snippets/snippets/connectors/go/hello.go + :language: go + :start-at: // Select by secondary key + :end-at: Tuple selected the secondary key value + :dedent: -.. code-block:: go - resp, err = conn.Upsert("tester", []interface{}{4, "Another band", 2000}, []interface{}{[]interface{}{"+", 2, 5}}) -This increases by 5 the value of the third field in the tuple with ``id = 4``, or -inserts the tuple ``(4, "Another band", 2000)`` if a tuple with this ``id`` -doesn't exist. +.. _getting_started_go_updating_data: -.. _getting_started-go-delete: +Updating data +************* -******************************************************************************** -Deleting data -******************************************************************************** +``NewUpdateRequest()`` can be used to update a tuple identified by the primary key as follows: + +.. literalinclude:: /code_snippets/snippets/connectors/go/hello.go + :language: go + :start-at: // Update + :end-at: Updated tuple + :dedent: + +``NewUpsertRequest()`` can be used to update an existing tuple or inserts a new one. +In the example below, a new tuple is inserted: -To delete a tuple, use ``connection.Delete``: +.. literalinclude:: /code_snippets/snippets/connectors/go/hello.go + :language: go + :start-at: // Upsert + :end-before: // Replace + :dedent: -.. code-block:: go - resp, err = conn.Delete("tester", "primary", []interface{}{4}) +In this example, ``NewReplaceRequest()`` is used to delete the existing tuple and insert a new one: -To delete all tuples in a space (or to delete an entire space), use ``Call``. -We'll focus on this function in more detail in the -:ref:`next ` section. +.. literalinclude:: /code_snippets/snippets/connectors/go/hello.go + :language: go + :start-at: // Replace + :end-at: Replaced tuple + :dedent: -To delete all tuples in a space, call ``space:truncate``: -.. code-block:: go - resp, err = conn.Call("box.space.tester:truncate", []interface{}{}) -To delete an entire space, call ``space:drop``. -This requires connecting to Tarantool as the ``admin`` user: +.. _getting_started_go_deleting_data: + +Deleting data +************* -.. code-block:: go +``NewDeleteRequest()`` in the example below is used to delete a tuple whose primary key value is ``5``: - resp, err = conn.Call("box.space.tester:drop", []interface{}{}) +.. literalinclude:: /code_snippets/snippets/connectors/go/hello.go + :language: go + :start-at: // Delete + :end-at: Deleted tuple + :dedent: -.. _getting_started-go-stored-procs: -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +.. _getting_started_go_stored_procedures: + Executing stored procedures -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +To execute a stored procedure, use ``NewCallRequest()``: + +.. literalinclude:: /code_snippets/snippets/connectors/go/hello.go + :language: go + :start-at: // Call + :end-at: Stored procedure result + :dedent: + + +.. _getting_started_go_closing_connection: + +Closing the connection +~~~~~~~~~~~~~~~~~~~~~~ + +The ``CloseGraceful()`` method can be used to close the connection when it is no longer needed: + +.. literalinclude:: /code_snippets/snippets/connectors/go/hello.go + :language: go + :start-at: // Close connection + :end-at: Connection is closed + :dedent: + +.. NOTE:: -Switch to the terminal window where Tarantool is running. + You can find the example with all the requests above on GitHub: `go `_. -.. NOTE:: - If you don't have a terminal window with remote connection to Tarantool, - check out these guides: - * :ref:`connecting to a local Tarantool instance ` - * :ref:`attaching to a Tarantool instance that runs in a Docker container ` +.. _getting_started_go_run_client_app: -Define a simple Lua function: +Starting a client application +----------------------------- -.. code-block:: lua +1. Execute the ``go get`` command to update dependencies in the ``go.mod`` file: - function sum(a, b) - return a + b - end + .. code-block:: console -Now we have a Lua function defined in Tarantool. To invoke this function from -``go``, use ``Call``: + $ go get github.com/tarantool/go-tarantool/v2 -.. code-block:: go +2. To run the resulting application, execute the ``go run`` command in the application directory: - resp, err = conn.Call("sum", []interface{}{2, 3}) + .. code-block:: console -To send bare Lua code for execution, use ``Eval``: + $ go run . + Inserted tuples: [[1 Roxette 1986]] [[2 Scorpions 1965]] [[3 Ace of Base 1987]] [[4 The Beatles 1960]] + Tuple selected the primary key value: [[1 Roxette 1986]] + Tuple selected the secondary key value: [[4 The Beatles 1960]] + Updated tuple: [[2 Pink Floyd 1965]] + Replaced tuple: [[1 Queen 1970]] + Deleted tuple: [[5 The Rolling Stones 1962]] + Stored procedure result: [[[2 Pink Floyd 1965] [4 The Beatles 1960]]] + Connection is closed -.. code-block:: go - resp, err = connection.Eval("return 4 + 5", []interface{}{}) .. _getting_started-go-comparison: -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Feature comparison -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +------------------ -There are two more connectors from the open-source community: +There are two more connectors from the open source community: * `viciious/go-tarantool `_ diff --git a/doc/how-to/getting_started_net_box.rst b/doc/how-to/getting_started_net_box.rst index 2bb229cec1..318e1101e4 100644 --- a/doc/how-to/getting_started_net_box.rst +++ b/doc/how-to/getting_started_net_box.rst @@ -14,6 +14,8 @@ For more information about the ``net.box`` module API, check :ref:`net_box-modul Sample database configuration ----------------------------- +.. connectors_sample_db_config_start + This section describes the :ref:`configuration ` of a sample database that allows remote connections: .. literalinclude:: /code_snippets/snippets/connectors/instances.enabled/sample_db/config.yaml @@ -32,6 +34,8 @@ The ``myapp.lua`` file looks as follows: You can find the full example on GitHub: `sample_db `_. +.. connectors_sample_db_config_end + From 65c7637c8aeb934f957d1c99eb7c3f8486b96a7e Mon Sep 17 00:00:00 2001 From: andreyaksenov Date: Wed, 15 May 2024 16:38:58 +0300 Subject: [PATCH 2/4] Connectors: Go sample --- .../snippets/connectors/go/README.md | 14 +++ .../snippets/connectors/go/go.mod | 10 ++ .../snippets/connectors/go/go.sum | 14 +++ .../snippets/connectors/go/hello.go | 105 ++++++++++++++++++ 4 files changed, 143 insertions(+) create mode 100644 doc/code_snippets/snippets/connectors/go/README.md create mode 100644 doc/code_snippets/snippets/connectors/go/go.mod create mode 100644 doc/code_snippets/snippets/connectors/go/go.sum create mode 100644 doc/code_snippets/snippets/connectors/go/hello.go diff --git a/doc/code_snippets/snippets/connectors/go/README.md b/doc/code_snippets/snippets/connectors/go/README.md new file mode 100644 index 0000000000..fd3ca99a22 --- /dev/null +++ b/doc/code_snippets/snippets/connectors/go/README.md @@ -0,0 +1,14 @@ +# Go + +A sample application containing requests from the [Connecting from Go](https://www.tarantool.io/en/doc/latest/how-to/getting_started_go) tutorial. + + +## Running + +Before running this sample, start an application that allows remote connections to a sample database: [sample_db](../instances.enabled/sample_db). + +Then, start this sample by executing the following command in the `go` directory: + +``` +$ go run . +``` diff --git a/doc/code_snippets/snippets/connectors/go/go.mod b/doc/code_snippets/snippets/connectors/go/go.mod new file mode 100644 index 0000000000..75a8728573 --- /dev/null +++ b/doc/code_snippets/snippets/connectors/go/go.mod @@ -0,0 +1,10 @@ +module example/hello + +go 1.22.3 + +require ( + github.com/tarantool/go-iproto v1.0.0 // indirect + github.com/tarantool/go-tarantool/v2 v2.1.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect +) diff --git a/doc/code_snippets/snippets/connectors/go/go.sum b/doc/code_snippets/snippets/connectors/go/go.sum new file mode 100644 index 0000000000..69bcf3d9c6 --- /dev/null +++ b/doc/code_snippets/snippets/connectors/go/go.sum @@ -0,0 +1,14 @@ +github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/tarantool/go-iproto v1.0.0 h1:quC4hdFhCuFYaCqOFgUxH2foRkhAy+TlEy7gQLhdVjw= +github.com/tarantool/go-iproto v1.0.0/go.mod h1:LNCtdyZxojUed8SbOiYHoc3v9NvaZTB7p96hUySMlIo= +github.com/tarantool/go-tarantool/v2 v2.1.0 h1:IY33WoS8Kqb+TxNnKbzu/7yVkiCNZGhbG5Gw0/tMfSk= +github.com/tarantool/go-tarantool/v2 v2.1.0/go.mod h1:cpjGW5FHAXIMf0PKZte70pMOeadw1MA/hrDv1LblWk4= +github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= +github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= +github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= +github.com/vmihailenco/tagparser/v2 v2.0.0/go.mod h1:Wri+At7QHww0WTrCBeu4J6bNtoV6mEfg5OIWRZA9qds= +gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/doc/code_snippets/snippets/connectors/go/hello.go b/doc/code_snippets/snippets/connectors/go/hello.go new file mode 100644 index 0000000000..3b8c6ff168 --- /dev/null +++ b/doc/code_snippets/snippets/connectors/go/hello.go @@ -0,0 +1,105 @@ +package main + +import ( + "context" + "fmt" + "github.com/tarantool/go-tarantool/v2" + "time" +) + +func main() { + ctx, cancel := context.WithTimeout(context.Background(), time.Second) + defer cancel() + dialer := tarantool.NetDialer{ + Address: "127.0.0.1:3301", + User: "sampleuser", + Password: "123456", + } + opts := tarantool.Opts{ + Timeout: time.Second, + } + + conn, err := tarantool.Connect(ctx, dialer, opts) + if err != nil { + fmt.Println("Connection refused:", err) + return + } + + // Interacting with the database + // Insert data + tuple1, err := conn.Do( + tarantool.NewInsertRequest("bands"). + Tuple([]interface{}{1, "Roxette", 1986}), + ).Get() + tuple2, err := conn.Do( + tarantool.NewInsertRequest("bands"). + Tuple([]interface{}{2, "Scorpions", 1965}), + ).Get() + tuple3, err := conn.Do( + tarantool.NewInsertRequest("bands"). + Tuple([]interface{}{3, "Ace of Base", 1987}), + ).Get() + tuple4, err := conn.Do( + tarantool.NewInsertRequest("bands"). + Tuple([]interface{}{4, "The Beatles", 1960}), + ).Get() + fmt.Println("Inserted tuples: ", tuple1, tuple2, tuple3, tuple4) + + // Select by primary key + data, err := conn.Do( + tarantool.NewSelectRequest("bands"). + Limit(10). + Iterator(tarantool.IterEq). + Key([]interface{}{uint(1)}), + ).Get() + fmt.Println("Tuple selected the primary key value:", data) + + // Select by secondary key + data, err = conn.Do( + tarantool.NewSelectRequest("bands"). + Index("band"). + Limit(10). + Iterator(tarantool.IterEq). + Key([]interface{}{"The Beatles"}), + ).Get() + fmt.Println("Tuple selected the secondary key value:", data) + + // Update + data, err = conn.Do( + tarantool.NewUpdateRequest("bands"). + Key(tarantool.IntKey{2}). + Operations(tarantool.NewOperations().Assign(1, "Pink Floyd")), + ).Get() + fmt.Println("Updated tuple:", data) + + // Upsert + data, err = conn.Do( + tarantool.NewUpsertRequest("bands"). + Tuple([]interface{}{uint(5), "The Rolling Stones", 1962}). + Operations(tarantool.NewOperations().Assign(1, "The Doors")), + ).Get() + + // Replace + data, err = conn.Do( + tarantool.NewReplaceRequest("bands"). + Tuple([]interface{}{1, "Queen", 1970}), + ).Get() + fmt.Println("Replaced tuple:", data) + + // Delete + data, err = conn.Do( + tarantool.NewDeleteRequest("bands"). + Key([]interface{}{uint(5)}), + ).Get() + fmt.Println("Deleted tuple:", data) + + // Call + data, err = conn.Do( + tarantool.NewCallRequest("get_bands_older_than").Args([]interface{}{1966}), + ).Get() + fmt.Println("Stored procedure result:", data) + + // Close connection + conn.CloseGraceful() + fmt.Println("Connection is closed") +} From 19f460036c2ddb4de3141b236a69fabd77ba2ade Mon Sep 17 00:00:00 2001 From: andreyaksenov Date: Thu, 16 May 2024 15:25:23 +0300 Subject: [PATCH 3/4] Connectors: Go tutorial - update per review --- .../snippets/connectors/go/go.mod | 10 +-- .../snippets/connectors/go/go.sum | 4 ++ .../snippets/connectors/go/hello.go | 61 +++++++++++++------ doc/how-to/getting_started_go.rst | 37 ++++++++--- doc/how-to/getting_started_net_box.rst | 2 +- 5 files changed, 82 insertions(+), 32 deletions(-) diff --git a/doc/code_snippets/snippets/connectors/go/go.mod b/doc/code_snippets/snippets/connectors/go/go.mod index 75a8728573..191575428a 100644 --- a/doc/code_snippets/snippets/connectors/go/go.mod +++ b/doc/code_snippets/snippets/connectors/go/go.mod @@ -3,8 +3,10 @@ module example/hello go 1.22.3 require ( - github.com/tarantool/go-iproto v1.0.0 // indirect - github.com/tarantool/go-tarantool/v2 v2.1.0 // indirect - github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect - github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect + github.com/google/uuid v1.3.0 // indirect + github.com/shopspring/decimal v1.3.1 // indirect + github.com/tarantool/go-iproto v1.0.0 // indirect + github.com/tarantool/go-tarantool/v2 v2.1.0 // indirect + github.com/vmihailenco/msgpack/v5 v5.3.5 // indirect + github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect ) diff --git a/doc/code_snippets/snippets/connectors/go/go.sum b/doc/code_snippets/snippets/connectors/go/go.sum index 69bcf3d9c6..199d48ec59 100644 --- a/doc/code_snippets/snippets/connectors/go/go.sum +++ b/doc/code_snippets/snippets/connectors/go/go.sum @@ -1,5 +1,9 @@ github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= +github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/shopspring/decimal v1.3.1 h1:2Usl1nmF/WZucqkFZhnfFYxxxu8LG21F6nPQBE5gKV8= +github.com/shopspring/decimal v1.3.1/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/tarantool/go-iproto v1.0.0 h1:quC4hdFhCuFYaCqOFgUxH2foRkhAy+TlEy7gQLhdVjw= diff --git a/doc/code_snippets/snippets/connectors/go/hello.go b/doc/code_snippets/snippets/connectors/go/hello.go index 3b8c6ff168..50fb643168 100644 --- a/doc/code_snippets/snippets/connectors/go/hello.go +++ b/doc/code_snippets/snippets/connectors/go/hello.go @@ -4,6 +4,9 @@ import ( "context" "fmt" "github.com/tarantool/go-tarantool/v2" + _ "github.com/tarantool/go-tarantool/v2/datetime" + _ "github.com/tarantool/go-tarantool/v2/decimal" + _ "github.com/tarantool/go-tarantool/v2/uuid" "time" ) @@ -27,23 +30,26 @@ func main() { // Interacting with the database // Insert data - tuple1, err := conn.Do( - tarantool.NewInsertRequest("bands"). - Tuple([]interface{}{1, "Roxette", 1986}), - ).Get() - tuple2, err := conn.Do( - tarantool.NewInsertRequest("bands"). - Tuple([]interface{}{2, "Scorpions", 1965}), - ).Get() - tuple3, err := conn.Do( - tarantool.NewInsertRequest("bands"). - Tuple([]interface{}{3, "Ace of Base", 1987}), - ).Get() - tuple4, err := conn.Do( - tarantool.NewInsertRequest("bands"). - Tuple([]interface{}{4, "The Beatles", 1960}), - ).Get() - fmt.Println("Inserted tuples: ", tuple1, tuple2, tuple3, tuple4) + tuples := [][]interface{}{ + {1, "Roxette", 1986}, + {2, "Scorpions", 1965}, + {3, "Ace of Base", 1987}, + {4, "The Beatles", 1960}, + } + var futures []*tarantool.Future + for _, tuple := range tuples { + request := tarantool.NewInsertRequest("bands").Tuple(tuple) + futures = append(futures, conn.Do(request)) + } + fmt.Println("Inserted tuples:") + for _, future := range futures { + result, err := future.Get() + if err != nil { + fmt.Println("Got an error:", err) + } else { + fmt.Println(result) + } + } // Select by primary key data, err := conn.Do( @@ -52,6 +58,9 @@ func main() { Iterator(tarantool.IterEq). Key([]interface{}{uint(1)}), ).Get() + if err != nil { + fmt.Println("Got an error:", err) + } fmt.Println("Tuple selected the primary key value:", data) // Select by secondary key @@ -62,6 +71,9 @@ func main() { Iterator(tarantool.IterEq). Key([]interface{}{"The Beatles"}), ).Get() + if err != nil { + fmt.Println("Got an error:", err) + } fmt.Println("Tuple selected the secondary key value:", data) // Update @@ -70,6 +82,9 @@ func main() { Key(tarantool.IntKey{2}). Operations(tarantool.NewOperations().Assign(1, "Pink Floyd")), ).Get() + if err != nil { + fmt.Println("Got an error:", err) + } fmt.Println("Updated tuple:", data) // Upsert @@ -78,12 +93,18 @@ func main() { Tuple([]interface{}{uint(5), "The Rolling Stones", 1962}). Operations(tarantool.NewOperations().Assign(1, "The Doors")), ).Get() + if err != nil { + fmt.Println("Got an error:", err) + } // Replace data, err = conn.Do( tarantool.NewReplaceRequest("bands"). Tuple([]interface{}{1, "Queen", 1970}), ).Get() + if err != nil { + fmt.Println("Got an error:", err) + } fmt.Println("Replaced tuple:", data) // Delete @@ -91,12 +112,18 @@ func main() { tarantool.NewDeleteRequest("bands"). Key([]interface{}{uint(5)}), ).Get() + if err != nil { + fmt.Println("Got an error:", err) + } fmt.Println("Deleted tuple:", data) // Call data, err = conn.Do( tarantool.NewCallRequest("get_bands_older_than").Args([]interface{}{1966}), ).Get() + if err != nil { + fmt.Println("Got an error:", err) + } fmt.Println("Stored procedure result:", data) // Close connection diff --git a/doc/how-to/getting_started_go.rst b/doc/how-to/getting_started_go.rst index 9c5bee060f..47bd018892 100644 --- a/doc/how-to/getting_started_go.rst +++ b/doc/how-to/getting_started_go.rst @@ -38,6 +38,8 @@ Now you can create a client Go application that makes requests to this database. Developing a client application ------------------------------- +Before you start, make sure you have `Go installed `__ on your computer. + .. _getting_started_go_create_client_app: Creating an application @@ -61,8 +63,8 @@ Creating an application .. _getting_started_go_import_: -Importing 'go-tarantool' -~~~~~~~~~~~~~~~~~~~~~~~~ +Importing 'go-tarantool' packages +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ In the ``hello.go`` file, declare a ``main`` package and import the following packages: @@ -72,11 +74,13 @@ In the ``hello.go`` file, declare a ``main`` package and import the following pa :end-before: func main() :dedent: +The packages for external MsgPack types, such as ``datetime``, ``decimal``, or ``uuid``, are required to parse these types in a response. + .. _getting_started_go_creating_connection: -Creating a connection -~~~~~~~~~~~~~~~~~~~~~ +Connecting to the database +~~~~~~~~~~~~~~~~~~~~~~~~~~ 1. Declare the ``main()`` function: @@ -114,11 +118,18 @@ Add the following code to insert four tuples into the ``bands`` space: .. literalinclude:: /code_snippets/snippets/connectors/go/hello.go :language: go :start-at: // Insert data - :end-at: Inserted tuples: + :end-before: // Select by primary key :dedent: -The ``NewInsertRequest()`` method creates an insert request object that is executed by the connection. +This code makes insert requests asynchronously: + +- The ``Future`` structure is used as a handle for asynchronous requests. +- The ``NewInsertRequest()`` method creates an insert request object that is executed by the connection. + +.. NOTE:: + Making requests asynchronously is the recommended way to perform data operations. + Further requests in this tutorial are made synchronously. .. _getting_started_go_querying_data: @@ -157,7 +168,7 @@ Updating data :end-at: Updated tuple :dedent: -``NewUpsertRequest()`` can be used to update an existing tuple or inserts a new one. +``NewUpsertRequest()`` can be used to update an existing tuple or insert a new one. In the example below, a new tuple is inserted: .. literalinclude:: /code_snippets/snippets/connectors/go/hello.go @@ -231,18 +242,24 @@ The ``CloseGraceful()`` method can be used to close the connection when it is no Starting a client application ----------------------------- -1. Execute the ``go get`` command to update dependencies in the ``go.mod`` file: +1. Execute the following ``go get`` commands to update dependencies in the ``go.mod`` file: .. code-block:: console $ go get github.com/tarantool/go-tarantool/v2 + $ go get github.com/tarantool/go-tarantool/v2/decimal + $ go get github.com/tarantool/go-tarantool/v2/uuid 2. To run the resulting application, execute the ``go run`` command in the application directory: .. code-block:: console $ go run . - Inserted tuples: [[1 Roxette 1986]] [[2 Scorpions 1965]] [[3 Ace of Base 1987]] [[4 The Beatles 1960]] + Inserted tuples: + [[1 Roxette 1986]] + [[2 Scorpions 1965]] + [[3 Ace of Base 1987]] + [[4 The Beatles 1960]] Tuple selected the primary key value: [[1 Roxette 1986]] Tuple selected the secondary key value: [[4 The Beatles 1960]] Updated tuple: [[2 Pink Floyd 1965]] @@ -258,7 +275,7 @@ Starting a client application Feature comparison ------------------ -There are two more connectors from the open source community: +There are two more connectors from the open-source community: * `viciious/go-tarantool `_ diff --git a/doc/how-to/getting_started_net_box.rst b/doc/how-to/getting_started_net_box.rst index 318e1101e4..c14fbc004f 100644 --- a/doc/how-to/getting_started_net_box.rst +++ b/doc/how-to/getting_started_net_box.rst @@ -22,7 +22,7 @@ This section describes the :ref:`configuration ` of a sample :language: yaml :dedent: -- The configuration contains one instance that listens incoming requests on the ``127.0.0.1:3301`` address. +- The configuration contains one instance that listens for incoming requests on the ``127.0.0.1:3301`` address. - ``sampleuser`` has :ref:`privileges ` to select and modify data in the ``bands`` space and execute the ``get_bands_older_than`` stored function. This user can be used to connect to the instance remotely. - ``myapp.lua`` defines how data is stored in a database and includes a stored function. From a6d55be3afb025329000e58c127ef16f6ffd9b53 Mon Sep 17 00:00:00 2001 From: andreyaksenov Date: Fri, 17 May 2024 10:49:04 +0300 Subject: [PATCH 4/4] Connectors: Go tutorial - update per TW review --- .../snippets/connectors/go/hello.go | 8 +++--- doc/how-to/getting_started_go.rst | 26 +++++++++---------- doc/how-to/getting_started_net_box.rst | 2 +- 3 files changed, 19 insertions(+), 17 deletions(-) diff --git a/doc/code_snippets/snippets/connectors/go/hello.go b/doc/code_snippets/snippets/connectors/go/hello.go index 50fb643168..ee93e43def 100644 --- a/doc/code_snippets/snippets/connectors/go/hello.go +++ b/doc/code_snippets/snippets/connectors/go/hello.go @@ -11,6 +11,7 @@ import ( ) func main() { + // Connect to the database ctx, cancel := context.WithTimeout(context.Background(), time.Second) defer cancel() dialer := tarantool.NetDialer{ @@ -28,7 +29,8 @@ func main() { return } - // Interacting with the database + // Interact with the database + // ... // Insert data tuples := [][]interface{}{ {1, "Roxette", 1986}, @@ -61,7 +63,7 @@ func main() { if err != nil { fmt.Println("Got an error:", err) } - fmt.Println("Tuple selected the primary key value:", data) + fmt.Println("Tuple selected by the primary key value:", data) // Select by secondary key data, err = conn.Do( @@ -74,7 +76,7 @@ func main() { if err != nil { fmt.Println("Got an error:", err) } - fmt.Println("Tuple selected the secondary key value:", data) + fmt.Println("Tuple selected by the secondary key value:", data) // Update data, err = conn.Do( diff --git a/doc/how-to/getting_started_go.rst b/doc/how-to/getting_started_go.rst index 47bd018892..4398f52596 100644 --- a/doc/how-to/getting_started_go.rst +++ b/doc/how-to/getting_started_go.rst @@ -5,7 +5,7 @@ Connecting from Go **Examples on GitHub**: `sample_db `_, `go `_ -The tutorial shows how to use the 2.x version of the `go-tarantool `__ library to create a Go application that connects to a remote Tarantool instance, performs CRUD operations, and executes a stored procedure. +The tutorial shows how to use the `go-tarantool `__ 2.x library to create a Go application that connects to a remote Tarantool instance, performs CRUD operations, and executes a stored procedure. You can find the full package documentation here: `Client in Go for Tarantool `__. @@ -24,7 +24,7 @@ Sample database configuration Starting a sample database application -------------------------------------- -Before creating and starting a client Go application, you need to run the :ref:`sample_db ` application using ``tt start``: +Before creating and starting a client Go application, you need to run the :ref:`sample_db ` application using :ref:`tt start `: .. code-block:: console @@ -94,8 +94,8 @@ Connecting to the database .. literalinclude:: /code_snippets/snippets/connectors/go/hello.go :language: go - :start-after: func main() - :end-at: // Interacting with the database + :start-at: // Connect to the database + :end-before: // Insert data :dedent: This code establishes a connection to a running Tarantool instance on behalf of ``sampleuser``. @@ -103,10 +103,10 @@ Connecting to the database -.. _getting_started_go_using_data_operations: +.. _getting_started_go_manipulating_data: -Using data operations -~~~~~~~~~~~~~~~~~~~~~ +Manipulating data +~~~~~~~~~~~~~~~~~ .. _getting_started_go_inserting_data: @@ -142,7 +142,7 @@ To get a tuple by the specified primary key value, use ``NewSelectRequest()`` to .. literalinclude:: /code_snippets/snippets/connectors/go/hello.go :language: go :start-at: // Select by primary key - :end-at: Tuple selected the primary key value + :end-at: Tuple selected by the primary key value :dedent: You can also get a tuple by the value of the specified index by using ``Index()``: @@ -150,7 +150,7 @@ You can also get a tuple by the value of the specified index by using ``Index()` .. literalinclude:: /code_snippets/snippets/connectors/go/hello.go :language: go :start-at: // Select by secondary key - :end-at: Tuple selected the secondary key value + :end-at: Tuple selected by the secondary key value :dedent: @@ -260,8 +260,8 @@ Starting a client application [[2 Scorpions 1965]] [[3 Ace of Base 1987]] [[4 The Beatles 1960]] - Tuple selected the primary key value: [[1 Roxette 1986]] - Tuple selected the secondary key value: [[4 The Beatles 1960]] + Tuple selected by the primary key value: [[1 Roxette 1986]] + Tuple selected by the secondary key value: [[4 The Beatles 1960]] Updated tuple: [[2 Pink Floyd 1965]] Replaced tuple: [[1 Queen 1970]] Deleted tuple: [[5 The Rolling Stones 1962]] @@ -272,8 +272,8 @@ Starting a client application .. _getting_started-go-comparison: -Feature comparison ------------------- +Go connectors feature comparison +-------------------------------- There are two more connectors from the open-source community: diff --git a/doc/how-to/getting_started_net_box.rst b/doc/how-to/getting_started_net_box.rst index c14fbc004f..44f4e73db2 100644 --- a/doc/how-to/getting_started_net_box.rst +++ b/doc/how-to/getting_started_net_box.rst @@ -24,7 +24,7 @@ This section describes the :ref:`configuration ` of a sample - The configuration contains one instance that listens for incoming requests on the ``127.0.0.1:3301`` address. - ``sampleuser`` has :ref:`privileges ` to select and modify data in the ``bands`` space and execute the ``get_bands_older_than`` stored function. This user can be used to connect to the instance remotely. -- ``myapp.lua`` defines how data is stored in a database and includes a stored function. +- ``myapp.lua`` defines the data model and a stored function. The ``myapp.lua`` file looks as follows: