func (bh *Header) Set(t Tag, value string) error {
	switch t {
	case versionTag:
		if value == "" {
			return errBadHeader
		}
		bh.Version = value
	case sortOrderTag:
		if value == "" {
			bh.SortOrder = UnknownOrder
			return nil
		}
		sortOrder, ok := sortOrderMap[value]
		if !ok {
			return errBadHeader
		}
		bh.SortOrder = sortOrder
	case groupOrderTag:
		if value == "" {
			bh.GroupOrder = GroupUnspecified
			return nil
		}
		groupOrder, ok := groupOrderMap[value]
		if !ok {
			return errBadHeader
		}
		bh.GroupOrder = groupOrder
	default:
		if value == "" {
			for i, tp := range bh.otherTags {
				if t == tp.tag {
					copy(bh.otherTags[i:], bh.otherTags[i+1:])
					bh.otherTags = bh.otherTags[:len(bh.otherTags)-1]
					return nil
				}
			}
		} else {
			for i, tp := range bh.otherTags {
				if t == tp.tag {
					bh.otherTags[i].value = value
					return nil
				}
			}
			bh.otherTags = append(bh.otherTags, tagPair{tag: t, value: value})
		}
	}
	return nil
}
Set sets the value associated with the given header line tag to the specified
value. If value is the empty string and the tag may be absent, it is deleted
or set to a meaningful default (SO:UnknownOrder and GO:GroupUnspecified),
otherwise an error is returned.
package sam
import (
	"bytes"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
)
var (
	errDupReference     = errors.New("sam: duplicate reference name")
	errDupReadGroup     = errors.New("sam: duplicate read group name")
	errDupProgram       = errors.New("sam: duplicate program name")
	errUsedReference    = errors.New("sam: reference already used")
	errUsedReadGroup    = errors.New("sam: read group already used")
	errUsedProgram      = errors.New("sam: program already used")
	errInvalidReference = errors.New("sam: reference not owned by header")
	errInvalidReadGroup = errors.New("sam: read group not owned by header")
	errInvalidProgram   = errors.New("sam: program not owned by header")
	errBadLen           = errors.New("sam: reference length out of range")
)
type SortOrder int
const (
	UnknownOrder SortOrder = iota
	Unsorted
	QueryName
	Coordinate
)
var (
	sortOrder = [...]string{
		UnknownOrder: "unknown",
		Unsorted:     "unsorted",
		QueryName:    "queryname",
		Coordinate:   "coordinate",
	}
	sortOrderMap = map[string]SortOrder{
		"unknown":    UnknownOrder,
		"unsorted":   Unsorted,
		"queryname":  QueryName,
		"coordinate": Coordinate,
	}
)
func (so SortOrder) String() string {
	if so < Unsorted || so > Coordinate {
		return sortOrder[UnknownOrder]
	}
	return sortOrder[so]
}
type GroupOrder int
const (
	GroupUnspecified GroupOrder = iota
	GroupNone
	GroupQuery
	GroupReference
)
var (
	groupOrder = [...]string{
		GroupUnspecified: "none",
		GroupNone:        "none",
		GroupQuery:       "query",
		GroupReference:   "reference",
	}
	groupOrderMap = map[string]GroupOrder{
		"none":      GroupNone,
		"query":     GroupQuery,
		"reference": GroupReference,
	}
)
func (g GroupOrder) String() string {
	if g < GroupNone || g > GroupReference {
		return groupOrder[GroupUnspecified]
	}
	return groupOrder[g]
}
type set map[string]int32
type Header struct {
	Version    string
	SortOrder  SortOrder
	GroupOrder GroupOrder
	otherTags  []tagPair
	refs       []*Reference
	rgs        []*ReadGroup
	progs      []*Program
	seenRefs   set
	seenGroups set
	seenProgs  set
	Comments []string
}
type tagPair struct {
	tag   Tag
	value string
}
func NewHeader(text []byte, r []*Reference) (*Header, error) {
	var err error
	bh := &Header{
		refs:       r,
		seenRefs:   set{},
		seenGroups: set{},
		seenProgs:  set{},
	}
	for i, r := range bh.refs {
		if r.owner != nil || r.id >= 0 {
			return nil, errUsedReference
		}
		r.owner = bh
		r.id = int32(i)
	}
	if text != nil {
		err = bh.UnmarshalText(text)
		if err != nil {
			return nil, err
		}
	}
	return bh, nil
}
func (bh *Header) Tags(fn func(t Tag, value string)) {
	if fn == nil {
		return
	}
	fn(versionTag, bh.Version)
	if bh.SortOrder != UnknownOrder {
		fn(sortOrderTag, bh.SortOrder.String())
	}
	if bh.GroupOrder != GroupNone {
		fn(groupOrderTag, bh.GroupOrder.String())
	}
	for _, tp := range bh.otherTags {
		fn(tp.tag, tp.value)
	}
}
func (bh *Header) Get(t Tag) string {
	switch t {
	case versionTag:
		return bh.Version
	case sortOrderTag:
		return bh.SortOrder.String()
	case groupOrderTag:
		return bh.GroupOrder.String()
	}
	for _, tp := range bh.otherTags {
		if t == tp.tag {
			return tp.value
		}
	}
	return ""
}