全部產品
Search
文件中心

Object Storage Service:類檔案唯讀(Go SDK V2)

更新時間:Aug 02, 2025

本文介紹如何使用Go SDK V2新增的File-Like介面訪問儲存空間的對象。

注意事項

  • 本文範例程式碼以華東1(杭州)的地區IDcn-hangzhou為例,預設使用外網Endpoint,如果您希望通過與OSS同地區的其他阿里雲產品訪問OSS,請使用內網Endpoint。關於OSS支援的Region與Endpoint的對應關係,請參見OSS地區和訪問網域名稱

  • 本文以從環境變數讀取存取憑證為例。如何配置訪問憑證,請參見配置訪問憑證

  • 要進行檔案下載,您必須有oss:GetObject許可權。具體操作,請參見為RAM使用者授予自訂的權限原則

方法定義

Go SDK V2新增了File-Like介面,以唯讀檔案(ReadOnlyFile)的方式訪問儲存空間的對象。

  • 提供了單流和並發+預取兩種模式,您可以根據情境需要調整並發數,以提升讀取速度。

  • 介面內部實現了串連斷掉重連的機制,在一些比較複雜的網路環境下,具備更好的魯棒性。

type ReadOnlyFile struct {
...
}

func (c *Client) OpenFile(ctx context.Context, bucket string, key string, optFns ...func(*OpenOptions)) (file *ReadOnlyFile, err error)

請求參數列表

參數名

類型

說明

ctx

context.Context

請求的上下文

bucket

string

設定儲存空間名稱

key

string

設定對象名

optFns

...func(*OpenOptions)

(可選)開啟檔案時的配置選項

其中,OpenOptions選項說明列舉如下:

參數名

類型

說明

Offset

int64

開啟檔案時的初始位移量,預設值是0

VersionId

*string

指定對象的版本號碼,多版本下有效

RequestPayer

*string

啟用了要求者付費模式時,需要設定為'requester'

EnablePrefetch

bool

是否啟用預模數式,預設不啟用

PrefetchNum

int

預取塊的數量,預設值為3。啟用預模數式時有效

ChunkSize

int64

每個預取塊的大小,預設值為6MiB。啟用預模數式時有效

PrefetchThreshold

int64

持續順序讀取多少位元組後進入到預模數式,預設值為20MiB。啟用預模數式時有效

傳回值列表

傳回值名

類型

說明

file

*ReadOnlyFile

唯讀檔案的執行個體,當 err 為nil 時有效,具體請參見ReadOnlyFile

err

error

開啟唯讀檔案的狀態,當失敗時,err 不為 nil

其中,ReadOnlyFile介面的常用方法列舉如下:

方法名

說明

Close() error

關閉檔案控制代碼,釋放資源,例如記憶體,活動的socket等

Read(p []byte) (int, error)

從資料來源中讀取長度為len(p)的位元組,儲存到p中,返回讀取的位元組數和遇到的錯誤

Seek(offset int64, whence int) (int64, error)

用於設定下一次讀或寫的位移量。其中whence的取值:0:相對於頭部,1:相對於當前位移量,2:相對於尾部

Stat() (os.FileInfo, error)

擷取對象的資訊,包括 對象大小,最後修改時間 以及元資訊

重要

注意:當預模數式開啟時,如果出現多次亂序讀時,則會自動退回單流模式。

範例程式碼

以單流模式讀取整個對象

package main

import (
	"context"
	"flag"
	"io"
	"log"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

// 定義全域變數
var (
	region     string // 儲存地區
	bucketName string // 儲存空間名稱
	objectName string // 對象名稱
)

// init函數用於初始化命令列參數
func init() {
	flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
	flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
	flag.StringVar(&objectName, "object", "", "The name of the object.")
}

func main() {
	// 解析命令列參數
	flag.Parse()

	// 檢查bucket名稱是否為空白
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// 檢查region是否為空白
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// 檢查object名稱是否為空白
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	// 載入預設配置並設定憑證提供者和地區
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// 建立OSS用戶端
	client := oss.NewClient(cfg)

	// 開啟檔案
	f, err := client.OpenFile(context.TODO(), bucketName, objectName)

	if err != nil {
		log.Fatalf("failed to open file %v", err)
	}
	defer f.Close()

	// 使用io.Copy讀取對象內容
	written, err := io.Copy(io.Discard, f)
	if err != nil {
		log.Fatalf("failed to read file %v", err)
	}

	log.Printf("read %d bytes from file", written)
}

啟用預模數式讀取整個對象

package main

import (
	"context"
	"flag"
	"io"
	"log"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

// 定義全域變數
var (
	region     string // 儲存地區
	bucketName string // 儲存空間名稱
	objectName string // 對象名稱
)

// init函數用於初始化命令列參數
func init() {
	flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
	flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
	flag.StringVar(&objectName, "object", "", "The name of the object.")
}

func main() {
	// 解析命令列參數
	flag.Parse()

	// 檢查bucket名稱是否為空白
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// 檢查region是否為空白
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// 檢查object名稱是否為空白
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	// 載入預設配置並設定憑證提供者和地區
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// 建立OSS用戶端
	client := oss.NewClient(cfg)

	// 開啟檔案
	f, err := client.OpenFile(context.TODO(),
		bucketName,
		objectName,
		func(oo *oss.OpenOptions) {
			oo.EnablePrefetch = true // 啟用預模數式
		})

	if err != nil {
		log.Fatalf("failed to open file %v", err)
	}

	defer f.Close()

	// 讀取檔案
	written, err := io.Copy(io.Discard, f)

	if err != nil {
		log.Fatalf("failed to read file %v", err)
	}

	log.Printf("read %d bytes from file", written)
}

通過Seek方法從指定位置開始讀取剩餘的資料

package main

import (
	"context"
	"flag"
	"io"
	"log"
	"net/http"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

// 定義全域變數
var (
	region     string // 儲存地區
	bucketName string // 儲存空間名稱
	objectName string // 對象名稱
)

// init函數用於初始化命令列參數
func init() {
	flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
	flag.StringVar(&bucketName, "bucket", "", "The name of the bucket.")
	flag.StringVar(&objectName, "object", "", "The name of the object.")
}

func main() {
	// 解析命令列參數
	flag.Parse()

	// 檢查bucket名稱是否為空白
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// 檢查region是否為空白
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// 檢查object名稱是否為空白
	if len(objectName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, object name required")
	}

	// 載入預設配置並設定憑證提供者和地區
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// 建立OSS用戶端
	client := oss.NewClient(cfg)

	// 開啟檔案
	f, err := client.OpenFile(context.TODO(), bucketName, objectName)

	if err != nil {
		log.Fatalf("failed to open file %v", err)
	}

	defer f.Close()

	// 擷取對象資訊
	info, _ := f.Stat()

	// 列印對象的基本屬性
	log.Printf("size:%v, mtime:%v\n", info.Size(), info.ModTime())

	// 對象中繼資料
	if header, ok := info.Sys().(http.Header); ok {
		log.Printf("content-type:%v\n", header.Get(oss.HTTPHeaderContentType))
	}

	// 設定讀取檔案的位移值,例如從123開始讀取
	_, err = f.Seek(123, io.SeekStart)
	if err != nil {
		log.Fatalf("failed to seek file %v", err)
	}

	// 使用io.Copy讀取檔案
	written, err := io.Copy(io.Discard, f)

	if err != nil {
		log.Fatalf("failed to read file %v", err)
	}

	log.Printf("read %d bytes from file", written)
}

相關文檔