func (b *BucketHandle) AddNotification(ctx context.Context, n *Notification) (ret *Notification, err error) {
	ctx = trace.StartSpan(ctx, "cloud.google.com/go/storage.Bucket.AddNotification")
	defer func() { trace.EndSpan(ctx, err) }()
	if n.ID != "" {
		return nil, errors.New("storage: AddNotification: ID must not be set")
	}
	if n.TopicProjectID == "" {
		return nil, errors.New("storage: AddNotification: missing TopicProjectID")
	}
	if n.TopicID == "" {
		return nil, errors.New("storage: AddNotification: missing TopicID")
	}
	call := b.c.raw.Notifications.Insert(b.name, toRawNotification(n))
	setClientHeader(call.Header())
	if b.userProject != "" {
		call.UserProject(b.userProject)
	}
	rn, err := call.Context(ctx).Do()
	if err != nil {
		return nil, err
	}
	return toNotification(rn), nil
}
AddNotification adds a notification to b. You must set n's TopicProjectID, TopicID
and PayloadFormat, and must not set its ID. The other fields are all optional. The
returned Notification's ID can be used to refer to it.
package storage
import (
	"context"
	"errors"
	"fmt"
	"regexp"
	"cloud.google.com/go/internal/trace"
	raw "google.golang.org/api/storage/v1"
)
type Notification struct {
	ID string
	TopicID string
	TopicProjectID string
	EventTypes []string
	ObjectNamePrefix string
	CustomAttributes map[string]string
	PayloadFormat string
}
const (
	NoPayload = "NONE"
	JSONPayload = "JSON_API_V1"
)
const (
	ObjectFinalizeEvent = "OBJECT_FINALIZE"
	ObjectMetadataUpdateEvent = "OBJECT_METADATA_UPDATE"
	ObjectDeleteEvent = "OBJECT_DELETE"
	ObjectArchiveEvent = "OBJECT_ARCHIVE"
)
func toNotification(rn *raw.Notification) *Notification {
	n := &Notification{
		ID:               rn.Id,
		EventTypes:       rn.EventTypes,
		ObjectNamePrefix: rn.ObjectNamePrefix,
		CustomAttributes: rn.CustomAttributes,
		PayloadFormat:    rn.PayloadFormat,
	}
	n.TopicProjectID, n.TopicID = parseNotificationTopic(rn.Topic)
	return n
}
var topicRE = regexp.MustCompile("^//pubsub.googleapis.com/projects/([^/]+)/topics/([^/]+)")
func parseNotificationTopic(nt string) (projectID, topicID string) {
	matches := topicRE.FindStringSubmatch(nt)
	if matches == nil {
		return "?", "?"
	}
	return matches[1], matches[2]
}
func toRawNotification(n *Notification) *raw.Notification {
	return &raw.Notification{
		Id: n.ID,
		Topic: fmt.Sprintf("//pubsub.googleapis.com/projects/%s/topics/%s",
			n.TopicProjectID, n.TopicID),
		EventTypes:       n.EventTypes,
		ObjectNamePrefix: n.ObjectNamePrefix,
		CustomAttributes: n.CustomAttributes,
		PayloadFormat:    string(n.PayloadFormat),
	}
}