func (cl *Client) ListBrokers(ctx context.Context) (BrokerDetails, error) {
	m, err := cl.Metadata(ctx)
	if err != nil {
		return nil, err
	}
	return m.Brokers, nil
}
ListBrokers issues a metadata request and returns BrokerDetails. This
returns an error if the request fails to be issued, or an *AuthError.
package kadm
import (
	"bytes"
	"context"
	"encoding/base64"
	"fmt"
	"sort"
	"github.com/twmb/franz-go/pkg/kerr"
	"github.com/twmb/franz-go/pkg/kgo"
	"github.com/twmb/franz-go/pkg/kmsg"
)
type TopicID [16]byte
func (t TopicID) String() string { return base64.StdEncoding.EncodeToString(t[:]) }
func (t TopicID) MarshalJSON() ([]byte, error) { return []byte(`"` + t.String() + `"`), nil }
func (t TopicID) Less(other TopicID) bool {
	return bytes.Compare(t[:], other[:]) == -1
}
type PartitionDetail struct {
	Topic     string  
	Partition int32   
	Leader          int32    
	LeaderEpoch     int32    
	Replicas        []int32  
	ISR             []int32  
	OfflineReplicas []int32  
	Err error  
}
type PartitionDetails map[int32]PartitionDetail
func (ds PartitionDetails) Sorted() []PartitionDetail {
	s := make([]PartitionDetail, 0, len(ds))
	for _, d := range ds {
		s = append(s, d)
	}
	sort.Slice(s, func(i, j int) bool { return s[i].Partition < s[j].Partition })
	return s
}
func (ds PartitionDetails) Numbers() []int32 {
	all := make([]int32, 0, len(ds))
	for p := range ds {
		all = append(all, p)
	}
	return int32s(all)
}
func (ds PartitionDetails) NumReplicas() int {
	for _, p := range ds {
		return len(p.Replicas)
	}
	return 0
}
type TopicDetail struct {
	Topic string  
	ID         TopicID           
	IsInternal bool              
	Partitions PartitionDetails  
	Err error  
}
type TopicDetails map[string]TopicDetail
func (ds TopicDetails) Names() []string {
	all := make([]string, 0, len(ds))
	for t := range ds {
		all = append(all, t)
	}
	sort.Strings(all)
	return all
}
func (ds TopicDetails) Sorted() []TopicDetail {
	s := make([]TopicDetail, 0, len(ds))
	for _, d := range ds {
		s = append(s, d)
	}
	sort.Slice(s, func(i, j int) bool {
		if s[i].Topic == "" {
			if s[j].Topic == "" {
				return bytes.Compare(s[i].ID[:], s[j].ID[:]) == -1
			}
			return true
		}
		if s[j].Topic == "" {
			return false
		}
		return s[i].Topic < s[j].Topic
	})
	return s
}
func (ds TopicDetails) Has(topic string) bool {
	d, ok := ds[topic]
	return ok && d.Err != kerr.UnknownTopicOrPartition
}
func (ds TopicDetails) FilterInternal() {
	for t, d := range ds {
		if d.IsInternal {
			delete(ds, t)
		}
	}
}
type Metadata struct {
	Cluster    string         
	Controller int32          
	Brokers    BrokerDetails  
	Topics     TopicDetails   
}
func int32s(is []int32) []int32 {
	sort.Slice(is, func(i, j int) bool { return is[i] < is[j] })
	return is
}