Go hello world

這個範例是一個非常簡單的「hello world」應用程式 (以 Go 語言撰寫),可以協助您瞭解如何進行下列各項操作:

  • 設定驗證方法
  • 連線至 Bigtable 執行個體。
  • 建立新的資料表。
  • 將資料寫入資料表。
  • 讀取資料。
  • 刪除資料表。

設定驗證方法

如要在本機開發環境中使用本頁的 Go 範例,請安裝並初始化 gcloud CLI,然後使用使用者憑證設定應用程式預設憑證。

  1. Install the Google Cloud CLI.

  2. If you're using an external identity provider (IdP), you must first sign in to the gcloud CLI with your federated identity.

  3. To initialize the gcloud CLI, run the following command:

    gcloud init
  4. If you're using a local shell, then create local authentication credentials for your user account:

    gcloud auth application-default login

    You don't need to do this if you're using Cloud Shell.

    If an authentication error is returned, and you are using an external identity provider (IdP), confirm that you have signed in to the gcloud CLI with your federated identity.

詳情請參閱 Set up authentication for a local development environment

執行範例

本範例使用 Go 適用的 Google Cloud 用戶端程式庫Cloud Bigtable 套件,與 Bigtable 進行通訊。

如要執行這個範例程式,請依照 GitHub 網頁上的說明操作。

搭配 Cloud 用戶端程式庫使用 Bigtable

這個應用程式範例會連線至 Bigtable,示範部分簡易作業。

匯入用戶端程式庫

本範例使用下列匯入功能:

import (
	"context"
	"flag"
	"fmt"
	"log"

	"cloud.google.com/go/bigtable"
)

連線至 Bigtable 以管理資料表

如要管理資料表,請使用 bigtable.NewAdminClient() 連線至 Bigtable。

adminClient, err := bigtable.NewAdminClient(ctx, *project, *instance)
if err != nil {
	log.Fatalf("Could not create admin client: %v", err)
}

建立資料表

使用 AdminClient.CreateTable() 建立資料表,然後使用 AdminClient.TableInfo() 取得資料表相關資訊。 使用 AdminClient.CreateColumnFamily() 建立資料欄系列。

tables, err := adminClient.Tables(ctx)
if err != nil {
	log.Fatalf("Could not fetch table list: %v", err)
}

if !sliceContains(tables, tableName) {
	log.Printf("Creating table %s", tableName)
	if err := adminClient.CreateTable(ctx, tableName); err != nil {
		log.Fatalf("Could not create table %s: %v", tableName, err)
	}
}

tblInfo, err := adminClient.TableInfo(ctx, tableName)
if err != nil {
	log.Fatalf("Could not read info for table %s: %v", tableName, err)
}

if !sliceContains(tblInfo.Families, columnFamilyName) {
	if err := adminClient.CreateColumnFamily(ctx, tableName, columnFamilyName); err != nil {
		log.Fatalf("Could not create column family %s: %v", columnFamilyName, err)
	}
}

連線至 Bigtable 以管理資料

如要管理資料,請使用 bigtable.NewClient() 連線至 Bigtable。

client, err := bigtable.NewClient(ctx, *project, *instance)
if err != nil {
	log.Fatalf("Could not create data operations client: %v", err)
}

將資料列寫入資料表

開啟您想要寫入的資料表。使用 bigtable.NewMutation() 在單一資料列上建立突變,然後使用 Mutation.Set() 在資料列中設定值。為每一個資料列產生一個不同的列鍵值。重複這些步驟,以建立多筆變異。最後,使用 Table.ApplyBulk() 將所有變異套用到資料表。

tbl := client.Open(tableName)
muts := make([]*bigtable.Mutation, len(greetings))
rowKeys := make([]string, len(greetings))

log.Printf("Writing greeting rows to table")
for i, greeting := range greetings {
	muts[i] = bigtable.NewMutation()
	muts[i].Set(columnFamilyName, columnName, bigtable.Now(), []byte(greeting))

	// Each row has a unique row key.
	//
	// Note: This example uses sequential numeric IDs for simplicity, but
	// this can result in poor performance in a production application.
	// Since rows are stored in sorted order by key, sequential keys can
	// result in poor distribution of operations across nodes.
	//
	// For more information about how to design a Bigtable schema for the
	// best performance, see the documentation:
	//
	//     https://cloud.google.com/bigtable/docs/schema-design
	rowKeys[i] = fmt.Sprintf("%s%d", columnName, i)
}

rowErrs, err := tbl.ApplyBulk(ctx, rowKeys, muts)
if err != nil {
	log.Fatalf("Could not apply bulk row mutation: %v", err)
}
if rowErrs != nil {
	for _, rowErr := range rowErrs {
		log.Printf("Error writing row: %v", rowErr)
	}
	log.Fatalf("Could not write some rows")
}

依索引鍵讀取資料列

透過 Table.ReadRow() 使用資料列的索引鍵來直接取得資料列。

log.Printf("Getting a single greeting by row key:")
row, err := tbl.ReadRow(ctx, rowKeys[0], bigtable.RowFilter(bigtable.ColumnFilter(columnName)))
if err != nil {
	log.Fatalf("Could not read row with key %s: %v", rowKeys[0], err)
}
log.Printf("\t%s = %s\n", rowKeys[0], string(row[columnFamilyName][0].Value))

掃描所有資料表資料列

使用 Table.ReadRows() 掃描資料表中的所有資料列。 使用完畢後,請關閉資料用戶端。

log.Printf("Reading all greeting rows:")
err = tbl.ReadRows(ctx, bigtable.PrefixRange(columnName), func(row bigtable.Row) bool {
	item := row[columnFamilyName][0]
	log.Printf("\t%s = %s\n", item.Row, string(item.Value))
	return true
}, bigtable.RowFilter(bigtable.ColumnFilter(columnName)))

if err = client.Close(); err != nil {
	log.Fatalf("Could not close data operations client: %v", err)
}

刪除資料表

使用 AdminClient.DeleteTable() 刪除資料表。使用完畢後,請關閉管理客戶端。

log.Printf("Deleting the table")
if err = adminClient.DeleteTable(ctx, tableName); err != nil {
	log.Fatalf("Could not delete table %s: %v", tableName, err)
}

if err = adminClient.Close(); err != nil {
	log.Fatalf("Could not close admin client: %v", err)
}

全面整合使用

以下是沒有註解的完整範例。


package main

import (
	"context"
	"flag"
	"fmt"
	"log"

	"cloud.google.com/go/bigtable"
)


const (
	tableName        = "Hello-Bigtable"
	columnFamilyName = "cf1"
	columnName       = "greeting"
)

var greetings = []string{"Hello World!", "Hello Cloud Bigtable!", "Hello Go!"}

func sliceContains(list []string, target string) bool {
	for _, s := range list {
		if s == target {
			return true
		}
	}
	return false
}

func main() {
	project := flag.String("project", "", "The Google Cloud Platform project ID. Required.")
	instance := flag.String("instance", "", "The Google Cloud Bigtable instance ID. Required.")
	flag.Parse()

	for _, f := range []string{"project", "instance"} {
		if flag.Lookup(f).Value.String() == "" {
			log.Fatalf("The %s flag is required.", f)
		}
	}

	ctx := context.Background()

	adminClient, err := bigtable.NewAdminClient(ctx, *project, *instance)
	if err != nil {
		log.Fatalf("Could not create admin client: %v", err)
	}

	tables, err := adminClient.Tables(ctx)
	if err != nil {
		log.Fatalf("Could not fetch table list: %v", err)
	}

	if !sliceContains(tables, tableName) {
		log.Printf("Creating table %s", tableName)
		if err := adminClient.CreateTable(ctx, tableName); err != nil {
			log.Fatalf("Could not create table %s: %v", tableName, err)
		}
	}

	tblInfo, err := adminClient.TableInfo(ctx, tableName)
	if err != nil {
		log.Fatalf("Could not read info for table %s: %v", tableName, err)
	}

	if !sliceContains(tblInfo.Families, columnFamilyName) {
		if err := adminClient.CreateColumnFamily(ctx, tableName, columnFamilyName); err != nil {
			log.Fatalf("Could not create column family %s: %v", columnFamilyName, err)
		}
	}

	client, err := bigtable.NewClient(ctx, *project, *instance)
	if err != nil {
		log.Fatalf("Could not create data operations client: %v", err)
	}

	tbl := client.Open(tableName)
	muts := make([]*bigtable.Mutation, len(greetings))
	rowKeys := make([]string, len(greetings))

	log.Printf("Writing greeting rows to table")
	for i, greeting := range greetings {
		muts[i] = bigtable.NewMutation()
		muts[i].Set(columnFamilyName, columnName, bigtable.Now(), []byte(greeting))

		rowKeys[i] = fmt.Sprintf("%s%d", columnName, i)
	}

	rowErrs, err := tbl.ApplyBulk(ctx, rowKeys, muts)
	if err != nil {
		log.Fatalf("Could not apply bulk row mutation: %v", err)
	}
	if rowErrs != nil {
		for _, rowErr := range rowErrs {
			log.Printf("Error writing row: %v", rowErr)
		}
		log.Fatalf("Could not write some rows")
	}

	log.Printf("Getting a single greeting by row key:")
	row, err := tbl.ReadRow(ctx, rowKeys[0], bigtable.RowFilter(bigtable.ColumnFilter(columnName)))
	if err != nil {
		log.Fatalf("Could not read row with key %s: %v", rowKeys[0], err)
	}
	log.Printf("\t%s = %s\n", rowKeys[0], string(row[columnFamilyName][0].Value))

	log.Printf("Reading all greeting rows:")
	err = tbl.ReadRows(ctx, bigtable.PrefixRange(columnName), func(row bigtable.Row) bool {
		item := row[columnFamilyName][0]
		log.Printf("\t%s = %s\n", item.Row, string(item.Value))
		return true
	}, bigtable.RowFilter(bigtable.ColumnFilter(columnName)))

	if err = client.Close(); err != nil {
		log.Fatalf("Could not close data operations client: %v", err)
	}

	log.Printf("Deleting the table")
	if err = adminClient.DeleteTable(ctx, tableName); err != nil {
		log.Fatalf("Could not delete table %s: %v", tableName, err)
	}

	if err = adminClient.Close(); err != nil {
		log.Fatalf("Could not close admin client: %v", err)
	}
}