分享方式:


如何搭配使用 Azure SDK for Go 與 Azure 資料表

適用於: 桌子

提示

本文中的內容適用於 Azure 資料表儲存體和 Azure Cosmos DB for Table。 API for Table 是資料表儲存體的進階供應項目,可提供輸送量最佳化的資料表、全域發佈,以及自動次要索引。

在本文中,您將了解如何使用 Azure SDK for Go 來建立、列出及刪除 Azure 資料表和資料表實體。

Azure 資料表可為您提供具有無結構描述設計的索引鍵屬性存放區,讓您將結構化的 NoSQL 資料儲存在雲端中。 由於 Azure 資料表儲存體並無結構描述,因此您可輕易隨著應用程式的需求發展調整資料。 存取資料表的資料和 API 對許多應用程式而言都是快速且符合成本效益的解決方案。

您可以使用表格儲存體或 Azure Cosmos DB 來儲存具彈性的資料集,例如 Web 應用程式的使用者資料、通訊錄、裝置資訊。 或者,您的服務所需的其他中繼資料類型。 您可以在資料表中儲存任意數目的實體,且儲存體帳戶可包含任意數目的資料表,最高可達儲存體帳戶的容量上限。

請依照本文的指示,了解如何使用 Azure SDK for Go 管理 Azure 資料表儲存體。

必要條件

設定您的環境

若要依照本教學課程操作,您將需要 Azure 資源群組、儲存體帳戶和資料表資源。 執行下列命令以設定環境:

  1. 建立 Azure 資源群組。

    az group create --name myResourceGroup --location eastus
    
  2. 接著,為新的 Azure 資料表建立 Azure 儲存體帳戶。

    az storage account create --name <storageAccountName> --resource-group myResourceGroup --location eastus --sku Standard_LRS
    
  3. 建立資料表資源。

    az storage table create --account-name <storageAccountName> --account-key 'storageKey' --name mytable
    

安裝套件

您需要兩個套件才能使用 Go 來管理 Azure 資料表:azidentityaztablesazidentity 套件可讓您向 Azure 進行驗證。 aztables 套件可讓您管理 Azure 中的資料表資源。 執行下列 Go 命令以安裝這些套件:

go get github.com/Azure/azure-sdk-for-go/sdk/data/aztables
go get github.com/Azure/azure-sdk-for-go/sdk/azidentity

若要深入了解驗證 Azure 的方法,請參閱使用 Azure SDK for Go 進行 Azure 驗證

建立範例應用程式

安裝套件之後,您可以建立使用 Azure SDK for Go 來管理 Azure 資料表的範例應用程式。 執行 go mod 命令以建立名為 azTableSample 的新模組。

go mod init azTableSample

接著,建立名為 main.go 的檔案,然後將下列內容複製到其中:

package main

import (
    "context"
    "encoding/json"
    "fmt"
    "os"

    "github.com/Azure/azure-sdk-for-go/sdk/azcore/to"
    "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
    "github.com/Azure/azure-sdk-for-go/sdk/data/aztables"
)

type InventoryEntity struct {
    aztables.Entity
    Price       float32
    Inventory   int32
    ProductName string
    OnSale      bool
}

type PurchasedEntity struct {
    aztables.Entity
    Price float32
    ProductName string
    OnSale bool
}

func getClient() *aztables.Client {
    accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT")
    if !ok {
        panic("AZURE_STORAGE_ACCOUNT environment variable not found")
    }

    tableName, ok := os.LookupEnv("AZURE_TABLE_NAME")
    if !ok {
        panic("AZURE_TABLE_NAME environment variable not found")
    }

    cred, err := azidentity.NewDefaultAzureCredential(nil)
    if err != nil {
        panic(err)
    }
    serviceURL := fmt.Sprintf("https://%s.table.core.windows.net/%s", accountName, tableName)
    client, err := aztables.NewClient(serviceURL, cred, nil)
    if err != nil {
        panic(err)
    }
    return client
}

func createTable(client *aztables.Client) {
    //TODO: Check access policy, Storage Blob Data Contributor role needed
    _, err := client.Create(context.TODO(), nil)
    if err != nil {
        panic(err)
    }
}

func addEntity(client *aztables.Client) {
    myEntity := InventoryEntity{
        Entity: aztables.Entity{
            PartitionKey: "pk001",
            RowKey:       "rk001",
        },
        Price:       3.99,
        Inventory:   20,
        ProductName: "Markers",
        OnSale:      false,
    }

    marshalled, err := json.Marshal(myEntity)
    if err != nil {
        panic(err)
    }

    _, err = client.AddEntity(context.TODO(), marshalled, nil) // TODO: Check access policy, need Storage Table Data Contributor role
    if err != nil {
        panic(err)
    }
}

func listEntities(client *aztables.Client) {
    listPager := client.List(nil)
    pageCount := 0
    for listPager.More() {
        response, err := listPager.NextPage(context.TODO())
        if err != nil {
            panic(err)
        }
        fmt.Printf("There are %d entities in page #%d\n", len(response.Entities), pageCount)
        pageCount += 1
    }
}

func queryEntity(client *aztables.Client) {
    filter := fmt.Sprintf("PartitionKey eq '%v' or RowKey eq '%v'", "pk001", "rk001")
    options := &aztables.ListEntitiesOptions{
        Filter: &filter,
        Select: to.StringPtr("RowKey,Price,Inventory,ProductName,OnSale"),
        Top:    to.Int32Ptr(15),
    }

    pager := client.List(options)
    for pager.More() {
        resp, err := pager.NextPage(context.Background())
        if err != nil {
            panic(err)
        }
        for _, entity := range resp.Entities {
            var myEntity PurchasedEntity 
            err = json.Unmarshal(entity, &myEntity)
            if err != nil {
                panic(err)
            }
            fmt.Println("Return custom type [PurchasedEntity]")
            fmt.Printf("Price: %v; ProductName: %v; OnSale: %v\n", myEntity.Price, myEntity.ProductName, myEntity.OnSale)
        }
    }
}

func deleteEntity(client *aztables.Client) {
    _, err := client.DeleteEntity(context.TODO(), "pk001", "rk001", nil)
    if err != nil {
        panic(err)
    }
}

func deleteTable(client *aztables.Client) {
    _, err := client.Delete(context.TODO(), nil)
    if err != nil {
        panic(err)
    }
}

func main() {

    fmt.Println("Authenticating...")
    client := getClient()

    fmt.Println("Creating a table...")
    createTable(client)

    fmt.Println("Adding an entity to the table...")
    addEntity(client)

    fmt.Println("Calculating all entities in the table...")
    listEntities(client)

    fmt.Println("Querying a specific entity...")
    queryEntity(client) 

    fmt.Println("Deleting an entity...")
    deleteEntity(client) 

    fmt.Println("Deleting a table...")
    deleteTable(client)
}

重要

請確定您用來進行驗證的帳戶有適當的存取原則可管理您的 Azure 儲存體帳戶。 若要執行上述程式碼,您的帳戶至少必須有儲存體 Blob 資料參與者角色和儲存體資料表資料參與者角色。

程式碼範例

驗證用戶端

// Lookup environment variables
accountName, ok := os.LookupEnv("AZURE_STORAGE_ACCOUNT")
if !ok {
  panic("AZURE_STORAGE_ACCOUNT environment variable not found")
}

tableName, ok := os.LookupEnv("AZURE_TABLE_NAME")
if !ok {
  panic("AZURE_TABLE_NAME environment variable not found")
}

// Create a credential
cred, err := azidentity.NewDefaultAzureCredential(nil)
if err != nil {
  panic(err)
}

// Create a table client
serviceURL := fmt.Sprintf("https://%s.table.core.windows.net/%s", accountName, tableName)
client, err := aztables.NewClient(serviceURL, cred, nil)
if err != nil {
  panic(err)
}

建立表格

// Create a table and discard the response
_, err := client.Create(context.TODO(), nil)
if err != nil {
  panic(err)
}

建立實體

// Define the table entity as a custom type
type InventoryEntity struct {
    aztables.Entity
    Price       float32
    Inventory   int32
    ProductName string
    OnSale      bool
}

// Define the entity values
myEntity := InventoryEntity{
    Entity: aztables.Entity{
        PartitionKey: "pk001",
        RowKey:       "rk001",
    },
    Price:       3.99,
    Inventory:   20,
    ProductName: "Markers",
    OnSale:      false,
}

// Marshal the entity to JSON
marshalled, err := json.Marshal(myEntity)
if err != nil {
    panic(err)
}

// Add the entity to the table
_, err = client.AddEntity(context.TODO(), marshalled, nil) // needs Storage Table Data Contributor role
if err != nil {
    panic(err)
}

取得實體

// Define the new custom type
type PurchasedEntity struct {
    aztables.Entity
    Price       float32
    ProductName string
    OnSale      bool
}

// Define the query filter and options
filter := fmt.Sprintf("PartitionKey eq '%v' or RowKey eq '%v'", "pk001", "rk001")
options := &aztables.ListEntitiesOptions{
    Filter: &filter,
    Select: to.StringPtr("RowKey,Price,Inventory,ProductName,OnSale"),
    Top:    to.Int32Ptr(15),
}

// Query the table for the entity
pager := client.List(options)
for pager.More() {
    resp, err := pager.NextPage(context.Background())
    if err != nil {
        panic(err)
    }
    for _, entity := range resp.Entities {
        var myEntity PurchasedEntity
        err = json.Unmarshal(entity, &myEntity)
        if err != nil {
            panic(err)
        }
        fmt.Println("Return custom type [PurchasedEntity]")
        fmt.Printf("Price: %v; ProductName: %v; OnSale: %v\n", myEntity.Price, myEntity.ProductName, myEntity.OnSale)
    }
}

刪除實體

_, err := client.DeleteEntity(context.TODO(), "pk001", "rk001", nil)
if err != nil {
  panic(err)
}

刪除資料表

_, err := client.Delete(context.TODO(), nil)
if err != nil {
  panic(err)
}

執行程式碼

剩下的工作就是執行應用程式。 但在執行此工作之前,必須先設定環境變數。 請建立兩個環境變數,並使用下列命令將其設定為適當的值:

export AZURE_STORAGE_ACCOUNT=<YourStorageAccountName> 
export AZURE_TABLE_NAME=<YourAzureTableName>

接下來,執行下列 go run 命令來執行應用程式:

go run main.go

清除資源

若要刪除資源群組及其所有剩餘資源,請執行下列命令︰

az group delete --resource-group myResourceGroup

下一步

在本快速入門中,您已了解如何建立 Azure Cosmos DB 帳戶、如何使用資料總管來建立資料表,以及如何執行應用程式。 現在,您可以使用資料表 API 來查詢您的資料。