自从我学习 Google Pub/Sub 库以来,我已经设置了 Pub/Sub 的本地实例并创建了 2 个应用程序:1 个用于发送消息,另一个用于接收消息。到目前为止一切顺利,我已经成功设置了订阅和主题,并且收到了消息,但我注意到了一个问题。我尝试发送带有嵌套结构字段的消息,但没有收到它们。这是我的代码:
发件人:
package main
import (
"context"
"encoding/json"
"fmt"
"io"
"os"
"cloud.google.com/go/pubsub"
"github.com/joho/godotenv"
)
type Payload struct {
ID string
Type string
Name string
Image
Thumbnail
}
type Image struct {
URL string
Width string
Height string
}
type Thumbnail struct {
URL string
Width string
Height string
}
func main() {
godotenv.Load(".env")
w := os.Stdout
projectID := os.Getenv("PROJECT_ID")
topicID := os.Getenv("TOPIC_ID")
message := Payload{
ID: "1",
Type: "image",
Name: "Image 1",
Image: Image{
URL: "https://example.com/image1",
Width: "100",
Height: "100",
},
Thumbnail: Thumbnail{
URL: "https://example.com/image1/thumb",
Width: "50",
Height: "50",
},
}
if err := publish(w, projectID, topicID, message); err != nil {
fmt.Fprintf(w, "Failed to publish: %v", err)
}
}
func publish(w io.Writer, projectID, topicID string, msg Payload) error {
ctx := context.Background()
client, err := pubsub.NewClient(ctx, projectID)
if err != nil {
return fmt.Errorf("create new client: %w", err)
}
defer client.Close()
t := client.Topic(topicID)
payload, err := json.Marshal(msg)
if err != nil {
return fmt.Errorf("marshal payload: %w", err)
}
result := t.Publish(ctx, &pubsub.Message{
Data: payload,
})
id, err := result.Get(ctx)
if err != nil {
return fmt.Errorf("pubsub: result.Get: %w", err)
}
fmt.Fprintf(w, "Published a message; msg ID: %v\n", id)
return nil
}
接收者:
package main
import (
"context"
"encoding/json"
"errors"
"fmt"
"log"
"os"
"cloud.google.com/go/pubsub"
)
type Payload struct {
ID string
Type string
Name string
Image
Thumbnail
}
type Image struct {
URL string
Width string
Height string
}
type Thumbnail struct {
URL string
Width string
Height string
}
func main() {
projectID := os.Getenv("PROJECT_ID")
subscriptionID := os.Getenv("SUBSCRIPTION_ID")
if err := readMessages(projectID, subscriptionID); err != nil {
fmt.Printf("read message: %v", err)
}
}
func readMessages(projectID, subscriptionID string) error {
ctx := context.Background()
client, err := pubsub.NewClient(ctx, projectID)
if err != nil {
return fmt.Errorf("create new client: %w", err)
}
defer client.Close()
sub := client.Subscription(subscriptionID)
err = sub.Receive(context.Background(), func(ctx context.Context, m *pubsub.Message) {
result := Payload{}
message := m.Data
if err := json.Unmarshal(message, &result); err != nil {
log.Printf("unmarshal message: %v", err)
m.Nack()
return
}
log.Printf("get message: %s", m.Data)
m.Ack()
})
if err != nil && !errors.Is(err, context.Canceled) {
return fmt.Errorf("receive message: %w", err)
}
return nil
}
接收方的结果是:收到消息:{"ID":"1","Type":"image","Name":"Image 1"}
我的问题是为什么我没有收到嵌套字段?
发现问题了。结构上缺少 JSON 标签。现在结构看起来像这样:
type Payload struct {
ID string `json:"ID"`
Type string `json:"Type"`
Name string `json:"Name"`
Image Image `json:"Image"`
Thumbnail Thumbnail `json:"Thumbnail"`
}
type Image struct {
URL string `json:"URL"`
Width string `json:"Width"`
Height string `json:"Height"`
}
type Thumbnail struct {
URL string `json:"URL"`
Width string `json:"Width"`
Height string `json:"Height"`
}
结果如下所示:
Got message: {"ID":"1","Type":"image","Name":"Image 1","Image":{"URL":"https://example.com/image1","Width":"100","Height":"100"},"Thumbnail":{"URL":"https://example.com/image1/thumb","Width":"50","Height":"50"}}