# #amazon-web-services #go #amazon-s3
Вопрос:
Я работаю с SDK AWS S3 в GoLang, играя с загрузками и загрузками в различные корзины. Мне интересно, есть ли более простой способ загружать структуры или объекты непосредственно в корзину?
У меня есть структура, представляющая событие:
type Event struct {
ID string
ProcessID string
TxnID string
Inputs map[string]interface{}
}
Что я хотел бы загрузить в корзину S3. Но код, который я нашел в документации, работает только для загрузки строк.
func Save(client S3Client, T interface{}, key string) bool {
svc := client.S3clientObject
input := amp;s3.PutObjectInput{
Body: aws.ReadSeekCloser(strings.NewReader("testing this one")),
Bucket: aws.String(GetS3Bucket()),
Key: aws.String(GetObjectKey(T, key)),
Metadata: map[string]*string{
"metadata1": aws.String("value1"),
"metadata2": aws.String("value2"),
},
}
Это позволяет успешно загрузить базовый файл в корзину S3, который при открытии просто читается как «тестирование этого». Есть ли способ загрузить в корзину, чтобы она загружала объект, а не просто строковое значение??
Любая помощь приветствуется, так как я новичок в Go и S3.
Редактировать
Это код, который я использую для функции Get:
func GetIt(client S3Client, T interface{}, key string) interface{} {
svc := client.S3clientObject
s3Key := GetObjectKey(T, key)
resp, err := svc.GetObject(amp;s3.GetObjectInput{
Bucket: aws.String(GetS3Bucket()),
Key: aws.String(s3Key),
})
if err != nil {
fmt.Println(err)
return err
}
result := json.NewDecoder(resp.Body).Decode(amp;T)
fmt.Println(result)
return json.NewDecoder(resp.Body).Decode(amp;T)
}
func main() {
client := b.CreateS3Client()
event := b.CreateEvent()
GetIt(client, event, key)
}
Ответ №1:
Закодируйте значение в байтах и загрузите байты. Вот как закодировать значение в байтах JSON:
func Save(client S3Client, value interface{}, key string) error {
p, err := json.Marshal(value)
if err != nil {
return err
}
input := amp;s3.PutObjectInput{
Body: aws.ReadSeekCloser(bytes.NewReader(p)),
…
}
…
}
Вызовите Сохранить значение, которое вы хотите загрузить:
value := amp;Event{ID: "an id", …}
err := Save(…, value, …)
if err != nil {
// handle error
}
Существует множество возможных вариантов, включая gob, xml и json, msgpack и т.д. Наилучший формат кодирования будет зависеть от требований вашего приложения.
Обратный процесс при получении объекта:
func GetIt(client S3Client, T interface{}, key string) error {
svc := client.S3clientObject
resp, err := svc.GetObject(amp;s3.GetObjectInput{
Bucket: aws.String(GetS3Bucket()),
Key: aws.String(key),
})
if err != nil {
return err
}
return json.NewDecoder(resp.Body).Decode(T)
}
Вызов GetIt с указателем на целевое значение:
var value model.Event
err := GetIt(client, amp;value, key)
if err != nil {
// handle error
}
fmt.Println(value) // prints the decoded value.
Комментарии:
1. Спасибо! Есть ли шанс, что вы знаете, как сделать обратное и декодировать значения, если бы я пытался загрузить событие из корзины S3 вместо загрузки?
2. Вызов Load с указателем на целевое значение вызывает «панику: ошибка во время выполнения: недопустимый адрес памяти или разыменование указателя с нулем» ошибка
3. Строка паникующего кода расшифровывается := json. Новый декодер(отв.Тело). Декодирование(значение)
4. Сейчас я получаю сообщение об ошибке, в котором говорится, что мой ключ не существует (он существует). Не уверен, почему это так, но я предполагаю, что это что-то выходит за рамки этой ошибки
5. Я предполагаю, что это связано с тем, что я передаю значение ключа в другую функцию, называемую GetObjectKey() (я оставил это, чтобы избежать путаницы), и поскольку ввод теперь является указателем, который портит эту функцию. Есть ли способ разыменовать событиеamp;, которое я передаю в main?
Ответ №2:
Приведенный здесь пример показывает, что S3 позволяет загружать все, что реализует интерфейс ввода-вывода.Reader. В примере используется strings.NewReader
синтаксис create a io.Reader
, который знает, как предоставить вызывающему объекту указанную строку. Ваша задача (согласно AWS здесь) состоит в том, чтобы выяснить, как адаптировать все, что вам нужно, для хранения в an io.Reader
.
Вы можете хранить байты непосредственно в кодировке JSON следующим образом
package main
import (
"bytes"
"encoding/json"
)
type Event struct {
ID string
ProcessID string
TxnID string
Inputs map[string]interface{}
}
func main() {
// To prepare the object for writing
b, err := json.Marshal(event)
if err != nil {
return
}
// pass this reader into aws.ReadSeekCloser(...)
reader := bytes.NewReader(b)
}
Комментарии:
1. Спасибо! Есть ли шанс, что вы знаете, как сделать обратное и декодировать значения, если бы я пытался загрузить событие из корзины S3 вместо загрузки?