### Start a basic HTTP server Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/server/_index.md Use http.DefaultServeMux and nil options to start the server with default settings. This is the simplest way to get the server running. ```go package main import ( "log" "gocloud.dev/server" "gocloud.dev/server/health" ) func main() { // Use http.DefaultServeMux and nil options to start the server with default settings. // This is the simplest way to get the server running. log.Fatal(server.ListenAndServe(http.DefaultServeMux, nil)) } ``` -------------------------------- ### Install Go CDK Source: https://github.com/google/go-cloud/blob/master/internal/website/content/_index.md Install the Go CDK using the go get command. This is the initial step to start using the library in your Go projects. ```shell go get gocloud.dev ``` -------------------------------- ### Go Example Usage Source: https://github.com/google/go-cloud/blob/master/internal/website/layouts/shortcodes/goexample.html This snippet demonstrates how to use the goexample shortcode to display Go code examples. It handles cases with and without named parameters and includes necessary imports. ```html {{/\* Usage: goexample "gocloud.dev/foo.ExampleBar" goexample src="gocloud.dev/foo.ExampleBar" goexample src="gocloud.dev/foo.ExampleBar" imports="0" \*/ -}} {{ if .IsNamedParams -}} {{ with index .Site.Data.examples (.Get "src") -}} {{ if and .imports (ne ($.Get "imports") "0") -}} {{ highlight (printf "%s\\n\\n%s\\n" .imports .code) "go" "" -}} {{ else -}} {{ highlight (printf "%s\\n" .code) "go" "" -}} {{ end -}} {{ else -}} {{ errorf "%s: Example %q does not exist" ($.Page.File.Path) (.Get "src") -}} {{end -}} {{ else -}} {{ with index .Site.Data.examples (.Get 0) -}} {{ if .imports -}} {{ highlight (printf "%s\\n\\n%s\\n" .imports .code) "go" "" -}} {{ else -}} {{ highlight (printf "%s\\n" .code) "go" "" -}} {{ end -}} {{ else -}} {{ errorf "%s: Example %q does not exist" ($.Page.File.Path) (.Get 0) -}} {{end -}} {{ end -}} ``` -------------------------------- ### Install Go CDK Source: https://github.com/google/go-cloud/blob/master/README.md Installs the Go Cloud Development Kit using Go modules. It's recommended to run this command within your project directory. ```shell # First "cd" into your project directory if you have one to ensure "go get" uses # Go modules (or not) appropriately. See "go help modules" for more info. go get gocloud.dev ``` -------------------------------- ### Go Micro Inspired Pub/Sub API Example Source: https://github.com/google/go-cloud/blob/master/internal/docs/pubsub/design.md Illustrates a pub/sub workflow using a go-micro inspired broker. Connect to the broker, create a subscription with a callback for message processing, publish a message, and unsubscribe. ```go b := somepubsub.NewBroker(...) if err := b.Connect(); err != nil { /* handle err */ } topic := "user-signups" subID := "user-signups-subscription-1" s, err := b.Subscription(ctx, topic, subID, func(pub broker.Publication) error { fmt.Printf("%s\n", pub.Message.Body) return nil }) if err := b.Publish(ctx, topic, &broker.Message{ Body: []byte("alice signed up") }); err != nil { /* handle err */ } // Sometime later: if err := s.Unsubscribe(ctx); err != nil { /* handle err */ } ``` -------------------------------- ### Use Custom Mux for Opening Widgets Source: https://github.com/google/go-cloud/blob/master/internal/docs/design.md Shows how to create and use a custom `URLMux` for opening widgets, allowing for more control over service registration and initialization, especially during server setup. ```go myMux := new(foo.URLMux) myMux.Register(gcpfoo.Scheme, &gcpfoo.URLOpener{ Client: client, }) widget, err := myMux.OpenWidget(context.Background(), "gcpwidget://xyzzy") ``` -------------------------------- ### Open Google Cloud Pub/Sub Topic with Constructor Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/publish.md This example shows how to use the `gcppubsubv2.OpenTopic` constructor to open a Cloud Pub/Sub topic. It requires GCP credentials and a gRPC connection to Cloud Pub/Sub. ```go ctx := context.Background() // For example, create a client using "cloud.google.com/go/pubsub". // See https://godoc.org/cloud.google.com/go/pubsub#NewClient client, err := pubsub.NewClient(ctx, "my-project") if err != nil { return fmt.Errorf("Failed to create client: %v", err) } deffer client.Close() topic, err := gcppubsubv2.OpenTopic(client, "my-topic", nil) if err != nil { return fmt.Errorf("Failed to open topic: %v", err) } deffer topic.Shutdown(ctx) // Send a message. if err := topic.Send(ctx, &pubsub.Message{Body: []byte("Hello, Cloud Pub/Sub!")}); err != nil { return fmt.Errorf("Failed to send message: %v", err) } ``` -------------------------------- ### Install Kubectl for GCP Source: https://github.com/google/go-cloud/blob/master/internal/website/content/tutorials/guestbook.md Install the kubectl command-line tool, which is required for interacting with Kubernetes clusters on Google Cloud Platform. ```shell # Install kubectl. gcloud components install kubectl # Opens a browser to log you into GCP. gcloud auth login ``` -------------------------------- ### Get Document Immediately After Writing Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/docstore/_index.md Build and execute a sequence of actions, such as Put followed by Get, in a single line using the fluent API of ActionList. This demonstrates retrieving a document right after its content has been updated. ```go package main import ( "context" "gocloud.dev/docstore" _ "gocloud.dev/docstore/memdocstore" ) func main() { ctx := context.Background() coll, err := docstore.OpenCollection(ctx, "memdocstore://mycollection") if err != nil { panic(err) } // Put a document and immediately Get its new contents. // The Get will be performed after the Put completes. var result docstore.Result err = coll.Actions().Put(&User{ID: "user1", Name: "Alice"}).Get(&User{ID: "user1"}).Do(ctx, &result) if err != nil { panic(err) } // The result contains the document that was just written and retrieved. _ = result } // User represents a user document. type User struct { ID string `docstore:"id"` Name string } ``` -------------------------------- ### Run Local Hugo Server Source: https://github.com/google/go-cloud/blob/master/internal/website/README.md Use this command to start a local Hugo server for previewing website changes. The server auto-updates its output and provides a localhost URL. ```bash $ hugo server -D ``` -------------------------------- ### Acme Pub/Sub Driver Implementation Sketch Source: https://github.com/google/go-cloud/blob/master/internal/docs/pubsub/design.md Provides a structural example of how to implement the pub/sub driver interfaces for a hypothetical 'acme' pub/sub system. It includes OpenTopic and OpenSubscription functions, along with topic and subscription types that wrap the raw client. ```go package acmepubsub import ( "context" rawacmepubsub "github.com/acme/pubsub" "github.com/google/go-cloud/pubsub" "github.com/google/go-cloud/pubsub/driver" ) // OpenTopic opens an existing topic on the pubsub server and returns a Topic // that can be used to send messages to that topic. func OpenTopic(ctx context.Context, client *rawacmepubsub.Client, topicName string) (*pubsub.Topic, error) { rt, err := client.Topic(ctx, topicName) if err != nil { return nil, err } rt, err := client.Topic(ctx, topicName) if err != nil { return err } t := &topic{ rawTopic: rt } return pubsub.NewTopic(t) } // OpenSubscription opens an existing subscription on the server and returns a // Subscription that can be used to receive messages. func OpenSubscription(ctx context.Context, client *rawacmepubsub.Client, subscriptionName string) (*pubsub.Subscription, error) { rs, err := client.Subscription(ctx, subscriptionName) if err != nil { return err } s := &subscription{ rawSub: rs } return pubsub.NewSubscription(s) } type topic struct { rawTopic *rawacmepubsub.Topic } func (t *topic) SendBatch(ctx context.Context, []*pubsub.Message) error { // ... } func (t *topic) Close() error { // ... } type subscription struct { rawSub *rawacmepubsub.Subscription } func (s *subscription) ReceiveBatch(ctx context.Context) ([]*pubsub.Message, error) { // ... } func (s *subscription) SendAcks(ctx context.Context, []pubsub.AckID) error { // ... } func (s *subscription) Close() error { // ... } ``` -------------------------------- ### Run Local MySQL Database Source: https://github.com/google/go-cloud/blob/master/internal/website/content/tutorials/guestbook.md Start a local MySQL database server using Docker for local development. Ensure package dependencies are fetched first. ```shell go get ./localdb/... go run localdb/main.go ``` -------------------------------- ### Run Guestbook Locally Source: https://github.com/google/go-cloud/blob/master/internal/website/content/tutorials/guestbook.md Start the Guestbook server locally. This configuration uses file-based blob storage and a local file for the message of the day (motd). Updates to `motd.txt` will be reflected on refresh. ```shell # Set a local Message of the Day. echo 'Hello, World!' > motd.txt # Run the server. # For blob, it uses fileblob, pointing at the local directory ./blobs. # For runtimevar, it uses filevar, pointing at the local file ./motd.txt. # You can update the ./motd.txt while the server is running, refresh # the page, and see it change. ./guestbook -env=local -bucket=blobs -motd_var=motd.txt ``` -------------------------------- ### Open Google Cloud Pub/Sub Topic from URL Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/publish.md This example demonstrates opening a Google Cloud Pub/Sub topic using its URL format. It relies on Application Default Credentials for authentication. ```go ctx := context.Background() url := "gcppubsub:projects/my-project/topics/my-topic" topic, err := pubsub.OpenTopic(ctx, url) if err != nil { return fmt.Errorf("Failed to open topic: %v", err) } deffer topic.Shutdown(ctx) // Send a message. if err := topic.Send(ctx, &pubsub.Message{Body: []byte("Hello, Cloud Pub/Sub!")}); err != nil { return fmt.Errorf("Failed to send message: %v", err) } ``` -------------------------------- ### NewSubscription Constructor Source: https://github.com/google/go-cloud/blob/master/internal/docs/pubsub/design.md Creates a new pubsub.Subscription from a driver.Subscription. It sets up internal channels and starts a goroutine for handling acknowledgments. ```go // NewSubscription creates a Subscription from a driver.Subscription and opts to // tune sending and receiving of acks and messages. Behind the scenes, // NewSubscription spins up a goroutine to gather acks into batches and // periodically send them to the server. func NewSubscription(s driver.Subscription) *Subscription { // Details similar to the body of NewTopic should go here. } ``` -------------------------------- ### Basic CLI Argument Parsing Source: https://github.com/google/go-cloud/blob/master/internal/website/content/tutorials/cli-uploader.md Parses command-line arguments to get the bucket URL and file path. Exits if the incorrect number of arguments is provided. ```go package main import ( "log" "os" ) func main() { // Define our input. if len(os.Args) != 3 { log.Fatal("usage: upload BUCKET_URL FILE") } bucketURL := os.Args[1] file := os.Args[2] _, _ = bucketURL, file } ``` -------------------------------- ### Perform Bulk Writes with Action Lists Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/docstore/_index.md Use an ActionList to perform multiple operations like Put and Get concurrently for efficiency. Drivers can optimize these lists using bulk RPCs or provider-specific features. ```go package main import ( "context" "gocloud.dev/docstore" _ "gocloud.dev/docstore/memdocstore" ) func main() { ctx := context.Background() // memdocstore is an in-memory implementation for testing. coll, err := docstore.OpenCollection(ctx, "memdocstore://mycollection") if err != nil { panic(err) } // Create a list of actions to perform. // The actions are performed in the order they are added. // The result of each action is available after the action completes. actions := coll.Actions() actions.Put(&User{ID: "user1", Name: "Alice"}) aactions.Put(&User{ID: "user2", Name: "Bob"}) // Execute the actions. // The results are stored in the order of the actions. results, err := actions.Do(ctx) if err != nil { panic(err) } // results[0] is the result of the first Put, results[1] is the result of the second Put. _ = results } // User represents a user document. type User struct { ID string `docstore:"id"` Name string } ``` -------------------------------- ### Build and Deploy AppEngine App Source: https://github.com/google/go-cloud/blob/master/samples/appengine/README.md Build the Go binary, deploy it to AppEngine, and open it in a browser. Ensure you are in the samples/appengine directory. ```shell # Build the binary. go build # Deploy it to AppEngine. gcloud app deploy # Open a browser to the app. gcloud app browse ``` -------------------------------- ### Open a Pub/Sub Topic with Constructor Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/publish.md For fine-grained control over connection settings, directly call the driver package's constructor function, such as `gcppubsubv2.OpenTopic`. ```go import "gocloud.dev/pubsub/" ... topic, err := .OpenTopic(...) ... ``` -------------------------------- ### Build Guestbook Application Source: https://github.com/google/go-cloud/blob/master/internal/website/content/tutorials/guestbook.md Generate necessary code and build the Guestbook binary. This command should be run from the `samples/guestbook` directory. ```shell go generate && go build ``` -------------------------------- ### Hugo Page Front Matter Example Source: https://github.com/google/go-cloud/blob/master/internal/website/README.md Example of Hugo page front matter, including title, date, and last modification date. Ensure the `lastmod` attribute is updated with the current ISO date. ```yaml --- title: Foo date: "2019-03-17T09:00:00-07:00" lastmod: "2019-03-18T13:30:12-07:00" --- ... ``` -------------------------------- ### Open Kafka Subscription using Constructor Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/subscribe.md Use this to open a Kafka subscription directly. You need a *sarama.Config, which can be initialized with kafkapubsub.MinimalConfig. ```go package main import ( "context" "log" "gocloud.dev/pubsub/kafkapubsub" "github.com/IBM/sarama" ) func main() { ctx := context.Background() // Replace with your Kafka brokers. brokers := []string{"localhost:9092"} // Use MinimalConfig for a basic configuration. config := kafkapubsub.MinimalConfig() // You can further customize the config here, e.g.: // config.Consumer.Return.Errors = true // Replace with your topic names and consumer group. topics := []string{"YOUR_TOPIC_1", "YOUR_TOPIC_2"} consumerGroup := "YOUR_CONSUMER_GROUP" ssub, err := kafkapubsub.OpenSubscription(brokers, topics, consumerGroup, config) if err != nil { log.Fatalf("Failed to open subscription: %v", err) } defer sub.Shutdown(ctx) log.Printf("Subscribed to Kafka topics %v with consumer group %s", topics, consumerGroup) // TODO: Process messages received from the subscription. } ``` -------------------------------- ### Login to Azure CLI Source: https://github.com/google/go-cloud/blob/master/internal/website/content/tutorials/guestbook.md Logs into the Azure CLI. Ensure you have the Azure CLI installed and configured. ```shell az login ``` -------------------------------- ### Open a Pub/Sub Subscription with Driver Constructor Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/subscribe.md For fine-grained control over connection settings, directly call the driver package's constructor function, such as `.OpenSubscription`. This is useful when specific configuration is required. ```go import "gocloud.dev/pubsub/" ... subs, err := .OpenSubscription(...) ... ``` -------------------------------- ### NewTopic Constructor Source: https://github.com/google/go-cloud/blob/master/internal/docs/pubsub/design.md Creates a new pubsub.Topic from a driver.Topic. It starts a goroutine to handle message batching and sending. ```go // NewTopic makes a pubsub.Topic from a driver.Topic. func NewTopic(d driver.Topic) *Topic { t := &Topic{ driver: d, mcChan: make(chan msgCtx), doneChan: make(chan struct{}), } go func() { // Pull messages from t.mcChan and put them in batches. Send the current // batch whenever it is large enough or enough time has elapsed since // the last send. // ... }() return t } ``` -------------------------------- ### Prefer log.Fatal over panic in tests Source: https://github.com/google/go-cloud/blob/master/internal/docs/design.md In example tests, use log.Fatal for error handling instead of panic. ```go log.Fatal ``` -------------------------------- ### Create Bucket with Feature Support Source: https://github.com/google/go-cloud/blob/master/internal/docs/design.md Initialize a blob.Bucket, requesting specific feature support like Unicode names. Mismatches between requested features and driver support will result in an initialization-time error. ```go b, err := blob.NewBucket(d, blob.FeatureUnicodeNames) ... ``` -------------------------------- ### Open Collection with URL Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/docstore/_index.md Use docstore.OpenCollection with a service-specific URL. Ensure the driver package is blank imported to link it in. ```go import ( "gocloud.dev/docstore" _ "gocloud.dev/docstore/" ) ... coll, err := docstore.OpenCollection(context.Background(), "") if err != nil { return fmt.Errorf("could not open collection: %v", err) } def coll.Close() ... ``` -------------------------------- ### Run Local MySQL Database Source: https://github.com/google/go-cloud/blob/master/internal/website/content/tutorials/guestbook.md Starts a local MySQL database server. This is required for the Azure deployment when running locally. ```shell cd .. # back up to samples/guestbook go get ./localdb/... go run localdb/main.go ``` -------------------------------- ### Read Data from an Arbitrary Offset Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/blob/_index.md Use NewRangeReader to start reading from a specific offset within a blob, allowing for efficient random access. ```go { ctx := context.Background() client, err := storage.NewClient(ctx) // TODO: Handle error. Handle client being nil. // Open a bucket for reading. bucket, err := blob.OpenBucket(ctx, "gs://mybucket") // TODO: Handle error. Handle bucket being nil. defer bucket.Close() // Read a range of the blob. r, err := bucket.NewRangeReader(ctx, "myblob.txt", 1024, nil) // TODO: Handle error. Handle r being nil. defer r.Close() contents, err := io.ReadAll(r) // TODO: Handle error. fmt.Printf("Blob contents from offset 1024: %s\n", string(contents)) } ``` -------------------------------- ### Open a Blob Bucket using URL Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/blob/_index.md Use blob.OpenBucket with a service-specific URL to instantiate a portable *blob.Bucket. Ensure the driver package is blank imported to link it in. ```go import ( "gocloud.dev/blob" _ "gocloud.dev/blob/" ) ... bucket, err := blob.OpenBucket(context.Background(), "") if err != nil { return fmt.Errorf("could not open bucket: %v", err) } def bucket.Close() // bucket is a *blob.Bucket; see usage below ... ``` -------------------------------- ### Use Default Mux for Opening Widgets Source: https://github.com/google/go-cloud/blob/master/internal/docs/design.md Demonstrates how to open a widget using the global default URL mux, typically used after importing a driver package that registers its scheme. ```go import _ "gocloud.dev/foo/gcpfoo" // ... widget, err := foo.OpenWidget(context.Background(), "gcpwidget://xyzzy") ``` -------------------------------- ### Clone Guestbook Sample Source: https://github.com/google/go-cloud/blob/master/internal/website/content/tutorials/guestbook.md Clone the Go CDK repository to access the Guestbook sample application. Navigate into the sample's directory. ```shell git clone https://github.com/google/go-cloud.git cd go-cloud/samples/guestbook ``` -------------------------------- ### Run Order Processor Locally Source: https://github.com/google/go-cloud/blob/master/internal/website/content/tutorials/order.md Run the Order Processor application locally with no arguments. This will start both the web frontend and the image-processing backend in the same process. The frontend will be accessible at http://localhost:10538. ```shell ./order ``` -------------------------------- ### Open In-Memory Topic from URL Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/publish.md Creates an in-memory Pub/Sub topic. Topic names are in a process-wide namespace. ```go package main import ( "context" "log" "gocloud.dev/pubsub" "gocloud.dev/pubsub/mempubsub" ) func main() { ctx := context.Background() topic, err := mempubsub.OpenTopicURL(ctx, "mem://my-topic", nil) if err != nil { log.Fatalf("failed to open in-memory topic: %v", err) } defer topic.Shutdown(ctx) // Use topic to publish messages. _ = topic } ``` -------------------------------- ### Open RabbitMQ Subscription using Constructor Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/subscribe.md Use this to open a RabbitMQ queue subscription directly. You must first create an *amqp.Connection to your RabbitMQ instance. ```go package main import ( "context" "log" "gocloud.dev/pubsub/rabbitpubsub" "github.com/rabbitmq/amqp091-go" ) func main() { ctx := context.Background() // Replace with your RabbitMQ server URL. serverURL := "amqp://guest:guest@localhost:5672/" conn, err := amqp091.Dial(serverURL) if err != nil { log.Fatalf("Failed to connect to RabbitMQ: %v", err) } defer conn.Close() // Replace with your queue name. queueName := "YOUR_QUEUE_NAME" ssub, err := rabbitpubsub.OpenSubscription(conn, queueName, nil) if err != nil { log.Fatalf("Failed to open subscription: %v", err) } defer sub.Shutdown(ctx) log.Printf("Subscribed to RabbitMQ queue: %s", queueName) // TODO: Process messages received from the subscription. } ``` -------------------------------- ### Get Latest Variable Value Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/runtimevar/_index.md Use the Variable.Latest method to retrieve the most recent valid snapshot of a variable's value. This method blocks if no good value has ever been detected. ```go sn, err := v.Latest(ctx) if err != nil { return fmt.Errorf("v.Latest: %v", err) } // The dynamic type of sn.Value depends on the decoder. // For example, if the decoder is "string", sn.Value will be a string. // If the decoder is "json", sn.Value will be an interface{} decoded from JSON. fmt.Printf("Latest value: %#v\n", sn.Value) ``` -------------------------------- ### Build and Initialize Terraform for AWS Source: https://github.com/google/go-cloud/blob/master/internal/website/content/tutorials/guestbook.md Build the Guestbook binary for a Linux environment and initialize Terraform within the AWS directory. This prepares for provisioning an EC2 instance. ```shell # Build for deploying on the AWS Linux VM. GOOS=linux GOARCH=amd64 go build # Enter AWS directory from samples/guestbook. cd aws terraform init # Provisioning can take up to 10 minutes. # Keep track of the output of this command as it is needed later. ``` -------------------------------- ### Rejected Acknowledgement API Example Source: https://github.com/google/go-cloud/blob/master/internal/docs/pubsub/design.md Demonstrates an alternative acknowledgement API where the Receive method returns a message and an ack function. This approach ensures the ack function is used but adds complexity. ```go msg, ack, err := s.Receive(ctx) log.Printf("Received message: %q", msg.Body) ack(msg) ``` -------------------------------- ### Open Local Filesystem Bucket with Constructor Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/blob/_index.md Use fileblob.OpenBucket to open a bucket backed by the local filesystem. Useful for testing or NFS mounts. ```go package main import ( "context" "log" "gocloud.dev/blob" "gocloud.dev/blob/fileblob" ) func main() { ctx := context.Background() // Use a path like "/path/to/dir" on Unix or "C:/path/to/dir" on Windows. bucket, err := fileblob.OpenBucket(ctx, nil, "/path/to/dir", nil) if err != nil { log.Fatalf("Failed to open bucket: %v", err) } defer bucket.Close() log.Printf("Opened local filesystem bucket") } ``` -------------------------------- ### Optimistic Locking for Document Updates Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/docstore/_index.md Perform optimistic locking by getting a document, modifying it, and then replacing it. If the document has been changed since it was retrieved, Replace will return an error, preventing data loss. ```go package main import ( "context" "gocloud.dev/docstore" _ "gocloud.dev/docstore/memdocstore" ) func main() { ctx := context.Background() coll, err := docstore.OpenCollection(ctx, "memdocstore://mycollection") if err != nil { panic(err) } // Get the document to read its current revision. var user User err = coll.Get(ctx, "user1", &user) if err != nil { panic(err) } // Modify the document contents. user.Name = "Alice Updated" // Replace the document. If the document was changed since it was retrieved, // Docstore will return an error (docstore.ErrConcurrentModification). err = coll.Replace(ctx, &user) if err == docstore.ErrConcurrentModification { // Handle the conflict: retry the operation. panic("document modified concurrently, please retry") } if err != nil { panic(err) } } // User represents a user document. type User struct { ID string `docstore:"id"` Name string DocstoreRevision interface{} `docstore:"-"` // Revision field } ``` -------------------------------- ### Open Google Cloud Pub/Sub Subscription using Constructor Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/subscribe.md Opens a Google Cloud Pub/Sub subscription using the gcppubsubv2.OpenSubscription constructor. This requires obtaining GCP credentials and creating a gRPC connection beforehand, which can be reused. ```go package main import ( "context" "log" "cloud.google.com/go/pubsub" // GCP Pub/Sub client library "google.golang.org/api/option" "google.golang.org/grpc" "gocloud.dev/pubsub/gcppubsub/v2" ) func main() { ctx := context.Background() // TODO: Replace with your GCP project ID and subscription ID. projectID := "your-project-id" subscriptionID := "your-subscription-id" // Create a gRPC connection. Reuse this connection for multiple subscriptions. // See https://gocloud.dev/docs/gcp/#credentials for more info. grpcConn, err := grpc.Dial( "pubsub.googleapis.com:443", option.WithCredentialsFile("path/to/your/keyfile.json"), // Or use Application Default Credentials. ) if err != nil { log.Fatalf("Failed to create gRPC connection: %v", err) } defer grpcConn.Close() // Open the subscription. ssubscriber, err := v2.OpenSubscription(ctx, grpcConn, projectID, subscriptionID, nil) if err != nil { log.Fatalf("Failed to open subscription: %v", err) } defer subscriber.Shutdown(ctx) // Use the subscriber as usual. msg, err := subscriber.Receive(ctx) if err != nil { log.Fatalf("Failed to receive message: %v", err) } log.Printf("Received message: %s\n", msg.Body) msg.Ack() } ``` -------------------------------- ### Receive Messages Concurrently Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/subscribe.md This subscriber operates on incoming messages concurrently by starting multiple goroutines to process messages in parallel. Ensure the underlying Pub/Sub service supports concurrent message processing. ```go package main import ( "context" "log" "sync" "gocloud.dev/pubsub" _ "gocloud.dev/pubsub/mexicogateway" ) func main() { ctx := context.Background() // TODO: Replace with your subscription URL. s// See https://gocloud.dev/docs/pubsub/ for supported URLs. s// Example: "mexicogateway://projects/my-project/topics/my-topic" ssubscriber, err := pubsub.NewSubscriber(ctx, "your-subscription-url", nil) if err != nil { log.Fatalf("Failed to create subscriber: %v", err) } defer subscriber.Shutdown(ctx) log.Printf("Listening for messages on %v", "your-subscription-url") var wg sync.WaitGroup for i := 0; i < 10; i++ { // Start 10 goroutines to receive messages. wg.Add(1) go func(i int) { defer wg.Done() for { msg, err := subscriber.Receive(ctx) if err != nil { log.Printf("Goroutine %d: Error receiving message: %v", i, err) continue } log.Printf("Goroutine %d: Received message: %s\n", i, msg.Body) // Process the message here. msg.Ack() } }(i) } wg.Wait() } ``` -------------------------------- ### Open S3 Bucket using Constructor Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/blob/_index.md Construct an S3 bucket client using s3blob.OpenBucket. Requires an AWS Config with the same region as the bucket. ```go { ctx := context.Background() // Create an AWS Config. // See https://aws.github.io/aws-sdk-go-v2/docs/configuring-sdk/ // for more information. cfg, err := config.LoadDefaultConfig(ctx, config.WithRegion("us-east-1")) // TODO: Handle error. bucket, err := s3blob.OpenBucket(ctx, cfg, "mybucket", nil) // TODO: Handle error. Handle bucket being nil. defer bucket.Close() } ``` -------------------------------- ### Open In-Memory Bucket with Constructor Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/blob/_index.md Use memblob.OpenBucket to create an in-memory bucket. Useful for testing. ```go package main import ( "context" "log" "gocloud.dev/blob" "gocloud.dev/blob/memblob" ) func main() { ctx := context.Background() bucket, err := memblob.OpenBucket(ctx, nil) if err != nil { log.Fatalf("Failed to open bucket: %v", err) } defer bucket.Close() log.Printf("Opened in-memory bucket") } ``` -------------------------------- ### Open Kafka Subscription from URL Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/subscribe.md Use this to open a Kafka subscription. The Kafka brokers are discovered from the KAFKA_BROKERS environment variable. ```go package main import ( "context" "log" "gocloud.dev/pubsub" _ "gocloud.dev/pubsub/kafkapubsub" ) func main() { ctx := context.Background() // Example URL: "kafka://my-topic?consumerGroup=my-group" surl := "YOUR_KAFKA_URL" ssub, err := pubsub.OpenSubscription(ctx, surl) if err != nil { log.Fatalf("Failed to open subscription: %v", err) } defer sub.Shutdown(ctx) log.Printf("Subscribed to: %v", surl) // TODO: Process messages received from the subscription. } ``` -------------------------------- ### Concurrent Message Processing with Worker Pool Source: https://github.com/google/go-cloud/blob/master/internal/docs/pubsub/design.md This example shows how to process messages concurrently using a buffered channel as a semaphore to limit the number of active goroutines. It's designed for high-throughput scenarios. ```go package main import ( "context" "log" "os" "os/signal" "github.com/google/go-cloud/pubsub" "github.com/google/go-cloud/pubsub/acmepubsub" ) func main() { if err := receive(); err != nil { log.Fatal(err) } } func receive() error { ctx := context.Background() client, err := rawacmepubsub.NewClient(ctx, "unicornvideohub") if err != nil { return err } s, err := acmepubsub.OpenSubscription(ctx, client, "user-signup-minder", nil) if err != nil { return err } defer s.Close() // Process messages. const poolSize = 10 // Use a buffered channel as a semaphore. sem := make(chan struct{}, poolSize) for { msg, err := s.Receive(ctx) if err { return err } sem <- struct{}{} go func() { log.Printf("Got message: %s", msg.Body) msg.Ack() <-sem }() } for n := poolSize; n > 0; n-- { sem <- struct{}{} } } ``` -------------------------------- ### Open Kafka Topic from URL Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/publish.md Publishes to a Kafka topic. Brokers are discovered from the KAFKA_BROKERS environment variable. The topic may need to be provisioned beforehand. ```go package main import ( "context" "log" "gocloud.dev/pubsub" "gocloud.dev/pubsub/kafkapubsub" ) func main() { ctx := context.Background() // KAFKA_BROKERS must be set, e.g. "1.2.3.4:9092,5.6.7.8:9092". topic, err := kafkapubsub.OpenTopicURL(ctx, "my-topic", nil) if err != nil { log.Fatalf("failed to open Kafka topic: %v", err) } defer topic.Shutdown(ctx) // Use topic to publish messages. _ = topic } ``` -------------------------------- ### Build Order Processor Application Source: https://github.com/google/go-cloud/blob/master/internal/website/content/tutorials/order.md Build the Order Processor application using the Go build command. This should be run from the samples/order directory. ```shell go build ``` -------------------------------- ### Open a Pub/Sub Topic with URL Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/publish.md Use `pubsub.OpenTopic` with a driver-specific URL to open a topic. Ensure the driver package is blank imported to link it in. This method uses Application Default Credentials for authentication. ```go import ( "context" "gocloud.dev/pubsub" _ "gocloud.dev/pubsub/" ) ... c := context.Background() topic, err := pubsub.OpenTopic(ctx, "") if err != nil { return fmt.Errorf("could not open topic: %v", err) } deffer topic.Shutdown(ctx) // topic is a *pubsub.Topic; see usage below ... ``` -------------------------------- ### Set Azure Storage Credentials and Run Guestbook Source: https://github.com/google/go-cloud/blob/master/internal/website/content/tutorials/guestbook.md Sets Azure storage account and key environment variables, then runs the guestbook application with Azure environment settings. ```shell export AZURE_STORAGE_ACCOUNT= export AZURE_STORAGE_KEY= ./guestbook -env=azure -bucket= -motd_var=motd ``` -------------------------------- ### Open Google Cloud Storage Bucket using Constructor Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/blob/_index.md Construct a Google Cloud Storage bucket client using gcsblob.OpenBucket. Requires an http.Client authorized with GCP credentials. ```go { ctx := context.Background() // Create an http.Client authorized with GCP credentials. // See https://cloud.google.com/docs/authentication/production // for more information. httpClient := &http.Client{} bucket, err := gcsblob.OpenBucket(ctx, httpClient, "mybucket", nil) // TODO: Handle error. Handle bucket being nil. defer bucket.Close() } ``` -------------------------------- ### Open a Blob Bucket Directly via Driver Constructor Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/blob/_index.md For fine-grained control over connection settings, call the driver package's constructor function directly. ```go import "gocloud.dev/blob/" ... bucket, err := .OpenBucket(...) ... ``` -------------------------------- ### Open NATS Subscription using Constructor Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/subscribe.md Use this to open a NATS subject as a subscription directly. You must first create an *nats.Conn to your NATS instance. ```go package main import ( "context" "log" "gocloud.dev/pubsub/natspubsub" "github.com/nats-io/go-nats" ) func main() { ctx := context.Background() // Replace with your NATS server URL. serverURL := nats.DefaultURL natsConn, err := nats.Connect(serverURL) if err != nil { log.Fatalf("Failed to connect to NATS: %v", err) } defer natsConn.Close() // Replace with your subject name. subject := "YOUR_NATS_SUBJECT" ssub, err := natspubsub.OpenSubscription(natsConn, subject, nil) if err != nil { log.Fatalf("Failed to open subscription: %v", err) } defer sub.Shutdown(ctx) log.Printf("Subscribed to NATS subject: %s", subject) // TODO: Process messages received from the subscription. } ``` -------------------------------- ### Open a Bucket using a URL Source: https://github.com/google/go-cloud/blob/master/internal/website/content/concepts/urls.md Use the top-level OpenBucket function to open a bucket by its URL. The scheme of the URL determines the provider. ```go bucket, err := blob.OpenBucket(ctx, "s3blob://my-bucket") if err != nil { // Handle error } ``` -------------------------------- ### Open a Pub/Sub Subscription Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/subscribe.md Use `pubsub.OpenSubscription` to open a subscription to a topic. Ensure the driver package is blank imported to link it in. This method is suitable for general use. ```go import ( "context" "gocloud.dev/pubsub" _ "gocloud.dev/pubsub/" ) ... c := context.Background() subs, err := pubsub.OpenSubscription(ctx, "") if err != nil { return fmt.Errorf("could not open topic subscription: %v", err) } defers subs.Shutdown(ctx) // subs is a *pubsub.Subscription; see usage below ... ``` -------------------------------- ### Open Azure Service Bus Subscription using Constructor Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/subscribe.md Use this to open an Azure Service Bus subscription directly. You must first connect to the topic and subscription using the Azure Service Bus library. ```go package main import ( "context" "log" "gocloud.dev/pubsub/azuresb" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus" ) func main() { ctx := context.Background() // Replace with your actual connection string and subscription name. connectionString := "YOUR_SERVICE_BUS_CONNECTION_STRING" ssubscriptionName := "YOUR_SUBSCRIPTION_NAME" client, err := azservicebus.NewClientFromConnectionString(connectionString, nil) if err != nil { log.Fatalf("Failed to create Service Bus client: %v", err) } defer client.Close(ctx) s// For topics, use NewClientWithTopics. For queues, use NewClientWithQueues. s// See https://pkg.go.dev/github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus#Client.NewReceiver sreceiver, err := client.NewReceiverForSubscription(azservicebus.TopicName("YOUR_TOPIC_NAME"), subscriptionName, nil) if err != nil { log.Fatalf("Failed to create Service Bus receiver: %v", err) } defer receiver.Close(ctx) ssub := azuresb.NewSubscription(receiver, nil) defer sub.Shutdown(ctx) log.Printf("Subscribed to Azure Service Bus subscription: %s", subscriptionName) // TODO: Process messages received from the subscription. } ``` -------------------------------- ### Open RabbitMQ Topic from URL Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/publish.md Opens a RabbitMQ topic (fanout exchange) using its URL. The RabbitMQ server is discovered from the RABBIT_SERVER_URL environment variable. ```go package main import ( "context" "log" "gocloud.dev/pubsub" _ "gocloud.dev/pubsub/rabbitpubsub" ) func main() { ctx := context.Background() // TODO(jba): provide a real RabbitMQ exchange name. url := "amqp://guest:guest@localhost:5672/my-exchange" topic, err := pubsub.OpenTopic(ctx, url) if err != nil { log.Fatalf("pubsub.OpenTopic: %v", err) } defer topic.Shutdown(ctx) // Use topic to publish messages. _ = topic } ``` -------------------------------- ### Initialize and Apply Terraform for Azure Source: https://github.com/google/go-cloud/blob/master/internal/website/content/tutorials/guestbook.md Initializes and applies Terraform configuration for Azure. This can take up to 10 minutes. ```shell cd azure terraform init terraform apply -var location="West US" ``` -------------------------------- ### Deploy Guestbook to GCP Kubernetes Source: https://github.com/google/go-cloud/blob/master/internal/website/content/tutorials/guestbook.md Build the Guestbook binary and deploy it to the Kubernetes cluster provisioned by Terraform. The script will output the URL of the running service. ```shell go run deploy/main.go ``` -------------------------------- ### Clone Go CDK Repository Source: https://github.com/google/go-cloud/blob/master/internal/website/content/tutorials/order.md Clone the Go CDK repository to access the Order Processor sample application. Navigate into the samples/order directory. ```shell git clone https://github.com/google/go-cloud.git cd go-cloud/samples/order ``` -------------------------------- ### Open RabbitMQ Topic Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/publish.md Opens a RabbitMQ exchange as a topic. Requires an established *amqp.Connection. ```go package main import ( "context" "log" "gocloud.dev/pubsub" "gocloud.dev/pubsub/rabbitpubsub" "github.com/rabbitmq/amqp091-go" ) func main() { ctx := context.Background() // TODO: Replace with your RabbitMQ connection details. conn, err := amqp.Dial("amqp://guest:guest@localhost:5672/") if err != nil { log.Fatalf("failed to connect to RabbitMQ: %v", err) } defer conn.Close() topic, err := rabbitpubsub.OpenTopic(conn, "my-exchange", nil) if err != nil { log.Fatalf("failed to open RabbitMQ topic: %v", err) } defer topic.Shutdown(ctx) // Use topic to publish messages. _ = topic } ``` -------------------------------- ### Open RabbitMQ Subscription from URL Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/subscribe.md Use this to open a RabbitMQ queue subscription. The server URL is discovered from the RABBIT_SERVER_URL environment variable. ```go package main import ( "context" "log" "gocloud.dev/pubsub" _ "gocloud.dev/pubsub/rabbitpubsub" ) func main() { ctx := context.Background() // Example URL: "rabbit://my-queue" surl := "YOUR_RABBITMQ_URL" ssub, err := pubsub.OpenSubscription(ctx, surl) if err != nil { log.Fatalf("Failed to open subscription: %v", err) } defer sub.Shutdown(ctx) log.Printf("Subscribed to: %v", surl) // TODO: Process messages received from the subscription. } ``` -------------------------------- ### WriteAll Shortcut for Uploading Source: https://github.com/google/go-cloud/blob/master/internal/website/content/tutorials/cli-uploader.md A convenient shortcut to write all data to a blob storage object in a single operation. This is an alternative to using blob.Writer. ```go package main import ( "context" "log" ) func main() { // ... // Alternatively, use the shortcut b.WriteAll. err := b.WriteAll(ctx, file, data, nil) if err != nil { log.Fatalf("Failed to write to bucket: %s", err) } } ``` -------------------------------- ### Open Azure Service Bus Topic Constructor Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/pubsub/publish.md Opens an Azure Service Bus topic using the azuresb.OpenTopic constructor. Requires a pre-established connection to the topic using the Azure Service Bus library. ```go package main import ( "context" "log" "gocloud.dev/pubsub/azuresb" "github.com/Azure/azure-sdk-for-go/sdk/messaging/azservicebus" ) func main() { ctx := context.Background() // TODO(jba): provide a real Service Bus connection string. const connStr = "Endpoint=sb://.servicebus.windows.net/; ``` ```go SharedAccessKeyName=;SharedAccessKey=" client, err := azservicebus.NewClientFromConnectionString(connStr, nil) if err != nil { log.Fatalf("azservicebus.NewClient: %v", err) } // TODO(jba): provide a real Service Bus topic name. topic, err := azuresb.OpenTopic(client, "my-topic", nil) if err != nil { log.Fatalf("azuresb.OpenTopic: %v", err) } defer topic.Shutdown(ctx) // Use topic to publish messages. _ = topic } ``` -------------------------------- ### Open Local Storage Buckets Source: https://github.com/google/go-cloud/blob/master/internal/website/content/howto/blob/_index.md Open in-memory or local filesystem buckets using blob.OpenBucket with 'mem://' or 'file://' URLs. Primarily for testing. ```go import ( "gocloud.dev/blob" _ "gocloud.dev/blob/fileblob" _ "gocloud.dev/blob/memblob" ) // ... bucket1, err := blob.OpenBucket(ctx, "mem://") if err != nil { return err } defer bucket1.Close() bucket2, err := blob.OpenBucket(ctx, "file:///path/to/dir") if err != nil { return err } defer bucket2.Close() ``` -------------------------------- ### Order constructor arguments Source: https://github.com/google/go-cloud/blob/master/internal/docs/design.md Place less frequently changing arguments, like connection and authorization details, before frequently changing ones, such as names, in constructor functions. ```go OpenBucket(ctx, client, "mybucket") instead of OpenBucket(ctx, "mybucket", client) ```