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 回复

不,因为里面有10个嵌套对象……

更多关于Golang中Partial Struct的定义与使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


结构体嵌入会有帮助吗?

type A struct {
  a int
}

type B struct {
  b int
}

type AndB struct {
  A
  B
}

在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)
        }
    }
}

这些方法允许你定义特定广告类型的部分结构体,同时保持通用方法的可用性。嵌入结构体提供了字段继承,接口允许多态行为,而函数选项模式提供了灵活的构造方式。

回到顶部