Getting Started with Azure Files in Go
This guide will walk you through the process of interacting with Azure File Storage using the Go programming language. Azure Files offers fully managed cloud file shares that are accessible via the industry-standard Server Message Block (SMB) protocol.
Prerequisites
- An Azure account with an active subscription.
- A storage account in Azure.
- Go installed on your system.
- The Azure SDK for Go.
Installing the Azure SDK for Go
You can install the necessary Azure SDK packages for Go using the go get command:
go get github.com/Azure/azure-sdk-for-go/sdk/storage/azblob
go get github.com/Azure/azure-sdk-for-go/sdk/storage/azfile
Connecting to Azure Files
To interact with Azure Files, you need to create a client. This typically involves providing your storage account name and a shared access signature (SAS) token or an account key.
Using Account Key:
import (
"context"
"fmt"
"log"
"os"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/file"
)
func main() {
accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME")
accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_KEY")
shareName := "myfileshare" // Replace with your share name
if accountName == "" || accountKey == "" {
log.Fatal("Please set AZURE_STORAGE_ACCOUNT_NAME and AZURE_STORAGE_ACCOUNT_KEY environment variables.")
}
// Create a file client using the account key
client, err := file.NewClient(accountName, file.NewSharedKeyCredential(accountName, accountKey), nil)
if err != nil {
log.Fatalf("Failed to create file client: %v", err)
}
ctx := context.Background()
// Example: List shares (optional)
sharesPager := client.NewListSharesPager(nil)
fmt.Println("Shares in the storage account:")
for sharesPager.More() {
page, err := sharesPager.NextPage(ctx)
if err != nil {
log.Fatalf("Failed to advance page for shares: %v", err)
}
for _, share := range page.Shares {
fmt.Printf("- %s\n", *share.Name)
}
}
// Get a client for a specific share
shareClient := client.NewShareClient(shareName)
fmt.Printf("Successfully obtained client for share: %s\n", shareName)
}
Using SAS Token:
import (
"context"
"fmt"
"log"
"os"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/file"
)
func main() {
accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME")
sasToken := os.Getenv("AZURE_STORAGE_SAS_TOKEN") // e.g., "?sv=2020-08-04&ss=bfqt&srt=sco&sp=rwdlacupx..."
shareName := "myfileshare" // Replace with your share name
if accountName == "" || sasToken == "" {
log.Fatal("Please set AZURE_STORAGE_ACCOUNT_NAME and AZURE_STORAGE_SAS_TOKEN environment variables.")
}
// Create a file client using the SAS token
// Note: The SAS token should include the leading '?'
client, err := file.NewClient(accountName, file.NewAnonymousClient(sasToken), nil)
if err != nil {
log.Fatalf("Failed to create file client: %v", err)
}
ctx := context.Background()
shareClient := client.NewShareClient(shareName)
fmt.Printf("Successfully obtained client for share: %s using SAS token\n", shareName)
}
Working with Directories and Files
Once you have a share client, you can manage directories and files within that share.
Creating a Directory
import (
"context"
"fmt"
"log"
"os"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/file"
)
func main() {
accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME")
accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_KEY")
shareName := "myfileshare"
directoryName := "mygo-directory"
client, err := file.NewClient(accountName, file.NewSharedKeyCredential(accountName, accountKey), nil)
if err != nil {
log.Fatalf("Failed to create file client: %v", err)
}
shareClient := client.NewShareClient(shareName)
dirClient := shareClient.NewDirectoryClient(directoryName)
ctx := context.Background()
_, err = dirClient.Create(ctx, nil)
if err != nil {
log.Fatalf("Failed to create directory: %v", err)
}
fmt.Printf("Directory '%s' created successfully in share '%s'.\n", directoryName, shareName)
}
Uploading a File
You can upload files using various methods. For simplicity, we'll use a direct upload. For larger files, consider resumable uploads.
import (
"context"
"fmt"
"log"
"os"
"strings"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/file"
)
func main() {
accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME")
accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_KEY")
shareName := "myfileshare"
directoryName := "mygo-directory"
fileName := "hello.txt"
fileContent := "Hello from Go and Azure Files!"
client, err := file.NewClient(accountName, file.NewSharedKeyCredential(accountName, accountKey), nil)
if err != nil {
log.Fatalf("Failed to create file client: %v", err)
}
shareClient := client.NewShareClient(shareName)
dirClient := shareClient.NewDirectoryClient(directoryName)
fileClient := dirClient.NewFileClient(fileName)
ctx := context.Background()
// Upload the file content
_, err = fileClient.UploadBuffer(ctx, []byte(fileContent), nil)
if err != nil {
log.Fatalf("Failed to upload file: %v", err)
}
fmt.Printf("File '%s' uploaded successfully to '%s/%s'.\n", fileName, directoryName, shareName)
}
Downloading a File
import (
"context"
"fmt"
"log"
"os"
"github.com/Azure/azure-sdk-for-go/sdk/storage/azfile/file"
)
func main() {
accountName := os.Getenv("AZURE_STORAGE_ACCOUNT_NAME")
accountKey := os.Getenv("AZURE_STORAGE_ACCOUNT_KEY")
shareName := "myfileshare"
directoryName := "mygo-directory"
fileName := "hello.txt"
localDownloadPath := "./downloaded-hello.txt"
client, err := file.NewClient(accountName, file.NewSharedKeyCredential(accountName, accountKey), nil)
if err != nil {
log.Fatalf("Failed to create file client: %v", err)
}
shareClient := client.NewShareClient(shareName)
dirClient := shareClient.NewDirectoryClient(directoryName)
fileClient := dirClient.NewFileClient(fileName)
ctx := context.Background()
// Download the file content
resp, err := fileClient.DownloadStream(ctx, nil)
if err != nil {
log.Fatalf("Failed to download file: %v", err)
}
defer resp.Body.Close()
// You can read the content directly or write to a file
// For simplicity, we'll print it here
content := make([]byte, resp.ContentLength)
_, err = resp.Body.Read(content)
if err != nil {
log.Fatalf("Failed to read downloaded content: %v", err)
}
fmt.Printf("Downloaded content of '%s':\n%s\n", fileName, string(content))
// Optionally, write to a local file
// err = os.WriteFile(localDownloadPath, content, 0644)
// if err != nil {
// log.Fatalf("Failed to write to local file: %v", err)
// }
// fmt.Printf("File downloaded and saved to: %s\n", localDownloadPath)
}
UploadFile function which handles chunking and retries automatically.
Error Handling
Always check for errors after each SDK operation. The Azure SDK for Go returns detailed error information that can help you diagnose issues.
Next Steps
Explore more advanced features such as:
- Setting file/directory properties (e.g., content type, metadata).
- Deleting files and directories.
- Listing contents of a directory.
- Working with snapshots.
- Implementing resumable uploads for very large files.
Refer to the official Azure SDK for Go documentation for comprehensive details and examples.