Golang中Partial Struct的定义与使用
Golang中Partial Struct的定义与使用 我正在处理Facebook营销API,不知道如何正确管理广告结构。
广告是一个庞大的结构体,我想定义广告的部分类型:
- 单图广告
- 合集广告
- 轮播广告
对于每种情况,它都是我完整广告结构体的一个子集。例如,对于创意部分:
type FacebookCreative struct {
ObjectStorySpec *FacebookObjectStorySpec `json:"object_story_spec,omitempty"`
Message string `json:"message,omitempty"`
Description string `json:"description,omitempty"`
ImageHash string `json:"image_hash,omitempty"`
CallToAction *struct {
Type string `json:"type,omitempty"`
} `json:"call_to_action,omitempty"`
AssetFeedSpec *struct {
Bodies []struct {
Text string `json:"text,omitempty"`
} `json:"bodies,omitempty"`
Descriptions []struct {
Text string `json:"text,omitempty"`
} `json:"descriptions,omitempty"`
CallToActionTypes []string `json:"call_to_action_types,omitempty"`
AdFormats []string `json:"ad_formats,omitempty"`
OptimizationType string `json:"optimization_type,omitempty"`
Images []struct {
Hash string `json:"hash,omitempty"`
} `json:"images,omitempty"`
Videos []struct {
Video string `json:"video_id,omitempty"`
} `json:"videos,omitempty"`
LinkURLs []struct {
WebsiteURL string `json:"website_url"`
} `json:"link_urls,omitempty"`
Titles []struct {
Text string `json:"text"`
} `json:"titles,omitempty"`
} `json:"asset_feed_spec,omitempty"`
ExternalID string `json:"id,omitempty"`
Title string `json:"title,omitempty"`
Body string `json:"body,omitempty"`
ImageURL string `json:"image_url,omitempty"`
ThumbnailURL string `json:"thumbnail_url,omitempty"`
ObjectType string `json:"object_type,omitempty"`
ActorType string `json:"actor_type,omitempty"`
Name string `json:"name,omitempty"`
AccessToken string `json:"access_token"`
Status string `json:"status"`
}
对于合集广告,我必须移除ObjectStorySpec部分;对于单图广告,则移除AssetFeedSpec部分。我想定义不包含不必要字段的部分类型,但最终又希望能够将这些类型用于适用于所有广告类型的通用方法…
我找到的唯一解决方案是将其序列化/反序列化成真正的类型…
有更好的主意吗?
更多关于Golang中Partial Struct的定义与使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
3 回复
在Go中处理部分结构体,可以通过嵌入和接口组合来实现。以下是几种实现方式:
1. 使用嵌入和类型别名
// 基础结构体
type FacebookCreative struct {
Message string `json:"message,omitempty"`
Description string `json:"description,omitempty"`
ImageHash string `json:"image_hash,omitempty"`
ExternalID string `json:"id,omitempty"`
Status string `json:"status"`
}
// 单图广告 - 移除AssetFeedSpec
type SingleImageCreative struct {
FacebookCreative
ObjectStorySpec *FacebookObjectStorySpec `json:"object_story_spec,omitempty"`
CallToAction *struct {
Type string `json:"type,omitempty"`
} `json:"call_to_action,omitempty"`
}
// 合集广告 - 移除ObjectStorySpec
type CollectionCreative struct {
FacebookCreative
AssetFeedSpec *struct {
Bodies []struct {
Text string `json:"text,omitempty"`
} `json:"bodies,omitempty"`
Images []struct {
Hash string `json:"hash,omitempty"`
} `json:"images,omitempty"`
} `json:"asset_feed_spec,omitempty"`
}
// 轮播广告
type CarouselCreative struct {
FacebookCreative
ObjectStorySpec *FacebookObjectStorySpec `json:"object_story_spec,omitempty"`
AssetFeedSpec *struct {
Images []struct {
Hash string `json:"hash,omitempty"`
} `json:"images,omitempty"`
} `json:"asset_feed_spec,omitempty"`
}
2. 使用接口实现通用方法
type Creative interface {
GetCommonFields() FacebookCreative
Validate() error
ToJSON() ([]byte, error)
}
func (c SingleImageCreative) GetCommonFields() FacebookCreative {
return c.FacebookCreative
}
func (c SingleImageCreative) Validate() error {
if c.ObjectStorySpec == nil {
return errors.New("object_story_spec is required for single image ads")
}
return nil
}
func (c SingleImageCreative) ToJSON() ([]byte, error) {
return json.Marshal(c)
}
// 通用处理方法
func ProcessCreative(creative Creative) error {
if err := creative.Validate(); err != nil {
return err
}
commonFields := creative.GetCommonFields()
// 处理通用字段
fmt.Printf("Processing creative with status: %s\n", commonFields.Status)
// 特定类型处理
switch c := creative.(type) {
case SingleImageCreative:
fmt.Println("Processing single image ad")
case CollectionCreative:
fmt.Println("Processing collection ad")
case CarouselCreative:
fmt.Println("Processing carousel ad")
}
return nil
}
3. 使用函数选项模式
type CreativeOption func(*FacebookCreative)
func WithObjectStorySpec(spec *FacebookObjectStorySpec) CreativeOption {
return func(c *FacebookCreative) {
c.ObjectStorySpec = spec
}
}
func WithAssetFeedSpec(spec interface{}) CreativeOption {
return func(c *FacebookCreative) {
// 根据类型设置不同的AssetFeedSpec
}
}
func NewSingleImageCreative(opts ...CreativeOption) SingleImageCreative {
creative := SingleImageCreative{}
for _, opt := range opts {
opt(&creative.FacebookCreative)
}
return creative
}
// 使用示例
spec := &FacebookObjectStorySpec{/* ... */}
singleImageAd := NewSingleImageCreative(
WithObjectStorySpec(spec),
)
4. 使用组合和私有字段
type creativeBase struct {
FacebookCreative
}
type SingleImageAd struct {
creativeBase
objectStorySpec *FacebookObjectStorySpec
}
func (s *SingleImageAd) ObjectStorySpec() *FacebookObjectStorySpec {
return s.objectStorySpec
}
func (s *SingleImageAd) SetObjectStorySpec(spec *FacebookObjectStorySpec) {
s.objectStorySpec = spec
}
// JSON序列化时自定义MarshalJSON
func (s SingleImageAd) MarshalJSON() ([]byte, error) {
type Alias SingleImageAd
return json.Marshal(&struct {
*Alias
ObjectStorySpec *FacebookObjectStorySpec `json:"object_story_spec,omitempty"`
}{
Alias: (*Alias)(&s),
ObjectStorySpec: s.objectStorySpec,
})
}
5. 实际使用示例
func main() {
// 创建单图广告
singleImage := SingleImageCreative{
FacebookCreative: FacebookCreative{
Message: "Single image ad message",
Status: "ACTIVE",
},
ObjectStorySpec: &FacebookObjectStorySpec{
// ... 具体字段
},
}
// 创建合集广告
collection := CollectionCreative{
FacebookCreative: FacebookCreative{
Message: "Collection ad message",
Status: "ACTIVE",
},
AssetFeedSpec: &struct {
Bodies []struct {
Text string `json:"text,omitempty"`
} `json:"bodies,omitempty"`
Images []struct {
Hash string `json:"hash,omitempty"`
} `json:"images,omitempty"`
}{
Images: []struct {
Hash string `json:"hash,omitempty"`
}{
{Hash: "image_hash_1"},
{Hash: "image_hash_2"},
},
},
}
// 使用通用接口处理
creatives := []Creative{singleImage, collection}
for _, creative := range creatives {
if err := ProcessCreative(creative); err != nil {
fmt.Printf("Error: %v\n", err)
}
}
}
这些方法允许你定义特定广告类型的部分结构体,同时保持通用方法的可用性。嵌入结构体提供了字段继承,接口允许多态行为,而函数选项模式提供了灵活的构造方式。


