Go용 Amazon QLDB 드라이버 — 퀵 스타트 튜토리얼 - Amazon Quantum 원장 데이터베이스(Amazon QLDB)

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

Go용 Amazon QLDB 드라이버 — 퀵 스타트 튜토리얼

중요

지원 종료 알림: 기존 고객은 2025년 7월 31일 지원이 종료될 QLDB 때까지 Amazon을 사용할 수 있습니다. 자세한 내용은 아마존 QLDB 원장을 Amazon Aurora SQL Postgre로 마이그레이션을 참조하십시오.

이 자습서에서는 Go용 Amazon QLDB 드라이버의 최신 버전을 사용하여 간단한 애플리케이션을 설정하는 방법을 알아봅니다. 이 안내서에는 드라이버 설치 단계와 기본 create, read, update, delete (CRUD) 작업의 단축 코드 예제가 포함되어 있습니다.

사전 조건

시작하기 전에 다음을 수행해야 합니다.

  1. 아직 Go 드라이버에 대한 사전 조건을 완료하지 않은 경우, 완료하세요. 여기에는 가입 AWS, 개발을 위한 프로그래밍 방식 액세스 권한 부여, Go 설치가 포함됩니다.

  2. quick-start라는 명칭의 원장을 생성합니다.

    원장 생성 방법을 알아보려면 콘솔 시작하기Amazon QLDB 원장의 기본 작업 또는 1단계: 새 원장 생성 섹션을 참조하세요.

1단계: 드라이버 설치

프로젝트에서 Go 모듈을 사용하여 프로젝트 종속성을 설치하는지 확인하세요.

프로젝트 디렉터리에 다음 go get 명령을 입력합니다.

$ go get -u github.com/awslabs/amazon-qldb-driver-go/v3/qldbdriver

드라이버를 설치하면 AWS SDK for Go v2Amazon Ion 패키지를 포함한 종속 항목도 설치됩니다.

2단계: 패키지 가져오기

다음 패키지를 가져오세요. AWS

import ( "context" "fmt" "github.com/amzn/ion-go/ion" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go-v2/config" "github.com/aws/aws-sdk-go-v2/service/qldbSession" "github.com/awslabs/amazon-qldb-driver-go/v3/qldbdriver" )

3단계: 드라이버 초기화

quick-start라는 명칭의 원장에 연결되는 드라이버의 인스턴스를 초기화합니다.

cfg, err := config.LoadDefaultConfig(context.TODO()) if err != nil { panic(err) } qldbSession := qldbsession.NewFromConfig(cfg, func(options *qldbsession.Options) { options.Region = "us-east-1" }) driver, err := qldbdriver.New( "quick-start", qldbSession, func(options *qldbdriver.DriverOptions) { options.LoggerVerbosity = qldbdriver.LogInfo }) if err != nil { panic(err) } defer driver.Shutdown(context.Background())
참고

이 코드 예제에서는 다음을 대체합니다.us-east-1 원장을 생성한 AWS 리전 곳으로 바꾸세요.

4단계: 테이블 및 인덱스 생성

다음 코드 예에서는 CREATE TABLECREATE INDEX 문을 실행하는 방법을 보여줍니다.

_, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { _, err := txn.Execute("CREATE TABLE People") if err != nil { return nil, err } // When working with QLDB, it's recommended to create an index on fields we're filtering on. // This reduces the chance of OCC conflict exceptions with large datasets. _, err = txn.Execute("CREATE INDEX ON People (firstName)") if err != nil { return nil, err } _, err = txn.Execute("CREATE INDEX ON People (age)") if err != nil { return nil, err } return nil, nil }) if err != nil { panic(err) }

이 코드는 People이라는 테이블을 만들고 해당 테이블의 agefirstName 필드를 인덱싱합니다. 인덱스는 쿼리 성능을 최적화하고 낙관적 동시성 제어 () OCC 충돌 예외를 제한하는 데 필요합니다.

5단계: 문서 삽입

다음 코드 예에서는 INSERT 문을 실행하는 방법을 보여줍니다. QLDBPartiQL 쿼리 언어 SQL (호환 가능) 및 Amazon Ion 데이터 형식 (상위 세트) 을 지원합니다. JSON

리터럴 PartiQL 사용

다음 코드는 문자열 리터럴 PartiQL 명령문을 사용하여 People 테이블에 문서를 삽입합니다.

_, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("INSERT INTO People {'firstName': 'Jane', 'lastName': 'Doe', 'age': 77}") }) if err != nil { panic(err) }

Ion 데이터 유형 사용

Go의 내장 JSON패키지와 마찬가지로 Ion에서 Go 데이터 유형을 마샬링하거나 Ion에서 정렬을 해제할 수 있습니다.

  1. 다음과 같이 Person이라는 이름의 Go 구조가 있는 경우.

    type Person struct { FirstName string `ion:"firstName"` LastName string `ion:"lastName"` Age int `ion:"age"` }
  2. Person의 인스턴스를 만듭니다.

    person := Person{"John", "Doe", 54}

    드라이버는 Ion 인코딩된 person의 텍스트 표현을 자동으로 마샬링합니다.

    중요

    마샬링과 마샬링 취소가 제대로 작동하려면 Go 데이터 구조의 필드 이름을 내보내야 합니다(첫 글자를 대문자로 표시).

  3. person 인스턴스를 트랜잭션의 Execute 메서드로 전달합니다.

    _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("INSERT INTO People ?", person) }) if err != nil { panic(err) }

    이 예에서는 물음표(?)를 변수 자리 표시자로 사용하여 문서 정보를 해당 문에 전달합니다. 자리 표시자를 사용할 때는 Ion 인코딩된 텍스트 값을 전달해야 합니다.

    작은 정보

    단일 INSERT 문을 사용하여 여러 문서를 삽입하려면 다음과 같이 목록 타입의 파라미터를 해당 문에 전달할 수 있습니다.

    // people is a list txn.Execute("INSERT INTO People ?", people)

    목록을 전달할 때 변수 자리 표시자(?)를 이중 꺾쇠 괄호( <<...>> )로 묶지 마세요. 수동 PartiQL 문에서 이중 꺾쇠 괄호는 으로 알려진 정렬되지 않은 모음을 의미합니다.

6단계: 문서 쿼리

다음 코드 예에서는 SELECT 문을 실행하는 방법을 보여줍니다.

p, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { result, err := txn.Execute("SELECT firstName, lastName, age FROM People WHERE age = 54") if err != nil { return nil, err } // Assume the result is not empty hasNext := result.Next(txn) if !hasNext && result.Err() != nil { return nil, result.Err() } ionBinary := result.GetCurrentData() temp := new(Person) err = ion.Unmarshal(ionBinary, temp) if err != nil { return nil, err } return *temp, nil }) if err != nil { panic(err) } var returnedPerson Person returnedPerson = p.(Person) if returnedPerson != person { fmt.Print("Queried result does not match inserted struct") }

이 예제에서는 People 테이블에서 문서를 쿼리하고 결과 세트가 비어 있지 않다고 가정하고 결과에서 문서를 반환합니다.

7단계: 문서 업데이트

다음 코드 예에서는 UPDATE 문을 실행하는 방법을 보여줍니다.

person.Age += 10 _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("UPDATE People SET age = ? WHERE firstName = ?", person.Age, person.FirstName) }) if err != nil { panic(err) }

8단계: 업데이트된 문서 쿼리

다음 코드 예제는 firstName으로 People 테이블을 쿼리하고 결과 세트의 모든 문서를 반환합니다.

p, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { result, err := txn.Execute("SELECT firstName, lastName, age FROM People WHERE firstName = ?", person.FirstName) if err != nil { return nil, err } var people []Person for result.Next(txn) { ionBinary := result.GetCurrentData() temp := new(Person) err = ion.Unmarshal(ionBinary, temp) if err != nil { return nil, err } people = append(people, *temp) } if result.Err() != nil { return nil, result.Err() } return people, nil }) if err != nil { panic(err) } var people []Person people = p.([]Person) updatedPerson := Person{"John", "Doe", 64} if people[0] != updatedPerson { fmt.Print("Queried result does not match updated struct") }

9단계: 테이블 삭제

다음 코드 예에서는 DROP TABLE 문을 실행하는 방법을 보여줍니다.

_, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("DROP TABLE People") }) if err != nil { panic(err) }

전체 애플리케이션 실행

다음 코드 예는 애플리케이션의 전체 버전입니다. 이전 단계를 개별적으로 수행하는 대신 이 코드 예를 처음부터 끝까지 복사하여 실행할 수도 있습니다. 이 애플리케이션은 이름이 지정된 원장에 대한 몇 가지 기본 CRUD 작업을 보여줍니다. quick-start

참고

이 코드를 실행하기 전에 quick-start 원장에 People이라는 명칭의 활성 테이블이 아직 없는지 확인하세요.

package main import ( "context" "fmt" "github.com/amzn/ion-go/ion" "github.com/aws/aws-sdk-go/aws" "github.com/aws/aws-sdk-go/aws/session" "github.com/aws/aws-sdk-go/service/qldbsession" "github.com/awslabs/amazon-qldb-driver-go/v2/qldbdriver" ) func main() { awsSession := session.Must(session.NewSession(aws.NewConfig().WithRegion("us-east-1"))) qldbSession := qldbsession.New(awsSession) driver, err := qldbdriver.New( "quick-start", qldbSession, func(options *qldbdriver.DriverOptions) { options.LoggerVerbosity = qldbdriver.LogInfo }) if err != nil { panic(err) } defer driver.Shutdown(context.Background()) _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { _, err := txn.Execute("CREATE TABLE People") if err != nil { return nil, err } // When working with QLDB, it's recommended to create an index on fields we're filtering on. // This reduces the chance of OCC conflict exceptions with large datasets. _, err = txn.Execute("CREATE INDEX ON People (firstName)") if err != nil { return nil, err } _, err = txn.Execute("CREATE INDEX ON People (age)") if err != nil { return nil, err } return nil, nil }) if err != nil { panic(err) } _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("INSERT INTO People {'firstName': 'Jane', 'lastName': 'Doe', 'age': 77}") }) if err != nil { panic(err) } type Person struct { FirstName string `ion:"firstName"` LastName string `ion:"lastName"` Age int `ion:"age"` } person := Person{"John", "Doe", 54} _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("INSERT INTO People ?", person) }) if err != nil { panic(err) } p, err := driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { result, err := txn.Execute("SELECT firstName, lastName, age FROM People WHERE age = 54") if err != nil { return nil, err } // Assume the result is not empty hasNext := result.Next(txn) if !hasNext && result.Err() != nil { return nil, result.Err() } ionBinary := result.GetCurrentData() temp := new(Person) err = ion.Unmarshal(ionBinary, temp) if err != nil { return nil, err } return *temp, nil }) if err != nil { panic(err) } var returnedPerson Person returnedPerson = p.(Person) if returnedPerson != person { fmt.Print("Queried result does not match inserted struct") } person.Age += 10 _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("UPDATE People SET age = ? WHERE firstName = ?", person.Age, person.FirstName) }) if err != nil { panic(err) } p, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { result, err := txn.Execute("SELECT firstName, lastName, age FROM People WHERE firstName = ?", person.FirstName) if err != nil { return nil, err } var people []Person for result.Next(txn) { ionBinary := result.GetCurrentData() temp := new(Person) err = ion.Unmarshal(ionBinary, temp) if err != nil { return nil, err } people = append(people, *temp) } if result.Err() != nil { return nil, result.Err() } return people, nil }) if err != nil { panic(err) } var people []Person people = p.([]Person) updatedPerson := Person{"John", "Doe", 64} if people[0] != updatedPerson { fmt.Print("Queried result does not match updated struct") } _, err = driver.Execute(context.Background(), func(txn qldbdriver.Transaction) (interface{}, error) { return txn.Execute("DROP TABLE People") }) if err != nil { panic(err) } }