func formatMapKey(v reflect.Value) string {
	var opts formatOptions
	opts.TypeMode = elideType
	opts.AvoidStringer = true
	opts.ShallowPointers = true
	s := opts.FormatValue(v, visitedPointers{}).String()
	return strings.TrimSpace(s)
}
formatMapKey formats v as if it were a map key.
The result is guaranteed to be a single line.
package cmp
import (
	"fmt"
	"reflect"
	"strconv"
	"strings"
	"unicode"
	"github.com/google/go-cmp/cmp/internal/flags"
	"github.com/google/go-cmp/cmp/internal/value"
)
type formatValueOptions struct {
	AvoidStringer bool
	ShallowPointers bool
	PrintAddresses bool
}
func (opts formatOptions) FormatType(t reflect.Type, s textNode) textNode {
	switch opts.TypeMode {
	case autoType:
		switch t.Kind() {
		case reflect.Struct, reflect.Slice, reflect.Array, reflect.Map:
			if s.Equal(textNil) {
				return s
			}
		default:
			return s
		}
	case elideType:
		return s
	}
	typeName := t.String()
	if t.Name() == "" {
		switch t.Kind() {
		case reflect.Chan, reflect.Func, reflect.Ptr:
			typeName = "(" + typeName + ")"
		}
		typeName = strings.Replace(typeName, "struct {", "struct{", -1)
		typeName = strings.Replace(typeName, "interface {", "interface{", -1)
	}
	if s, ok := s.(textWrap); ok {
		hasParens := strings.HasPrefix(s.Prefix, "(") && strings.HasSuffix(s.Suffix, ")")
		hasBraces := strings.HasPrefix(s.Prefix, "{") && strings.HasSuffix(s.Suffix, "}")
		if hasParens || hasBraces {
			return textWrap{typeName, s, ""}
		}
	}
	return textWrap{typeName + "(", s, ")"}
}
func (opts formatOptions) FormatValue(v reflect.Value, m visitedPointers) (out textNode) {
	if !v.IsValid() {
		return nil
	}
	t := v.Type()
	if !opts.AvoidStringer && v.CanInterface() {
		if (t.Kind() != reflect.Ptr && t.Kind() != reflect.Interface) || !v.IsNil() {
			switch v := v.Interface().(type) {
			case error:
				return textLine("e" + formatString(v.Error()))
			case fmt.Stringer:
				return textLine("s" + formatString(v.String()))
			}
		}
	}
	var skipType bool
	defer func() {
		if !skipType {
			out = opts.FormatType(t, out)
		}
	}()
	var ptr string
	switch t.Kind() {
	case reflect.Bool:
		return textLine(fmt.Sprint(v.Bool()))
	case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
		return textLine(fmt.Sprint(v.Int()))
	case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
		if t.PkgPath() == "" || t.Kind() == reflect.Uintptr {
			return textLine(formatHex(v.Uint()))
		}
		return textLine(fmt.Sprint(v.Uint()))
	case reflect.Float32, reflect.Float64:
		return textLine(fmt.Sprint(v.Float()))
	case reflect.Complex64, reflect.Complex128:
		return textLine(fmt.Sprint(v.Complex()))
	case reflect.String:
		return textLine(formatString(v.String()))
	case reflect.UnsafePointer, reflect.Chan, reflect.Func:
		return textLine(formatPointer(v))
	case reflect.Struct:
		var list textList
		for i := 0; i < v.NumField(); i++ {
			vv := v.Field(i)
			if value.IsZero(vv) {
				continue  
			}
			s := opts.WithTypeMode(autoType).FormatValue(vv, m)
			list = append(list, textRecord{Key: t.Field(i).Name, Value: s})
		}
		return textWrap{"{", list, "}"}
	case reflect.Slice:
		if v.IsNil() {
			return textNil
		}
		if opts.PrintAddresses {
			ptr = formatPointer(v)
		}
		fallthrough
	case reflect.Array:
		var list textList
		for i := 0; i < v.Len(); i++ {
			vi := v.Index(i)
			if vi.CanAddr() {  
				p := vi.Addr()
				if m.Visit(p) {
					var out textNode
					out = textLine(formatPointer(p))
					out = opts.WithTypeMode(emitType).FormatType(p.Type(), out)
					out = textWrap{"*", out, ""}
					list = append(list, textRecord{Value: out})
					continue
				}
			}
			s := opts.WithTypeMode(elideType).FormatValue(vi, m)
			list = append(list, textRecord{Value: s})
		}
		return textWrap{ptr + "{", list, "}"}
	case reflect.Map:
		if v.IsNil() {
			return textNil
		}
		if m.Visit(v) {
			return textLine(formatPointer(v))
		}
		var list textList
		for _, k := range value.SortKeys(v.MapKeys()) {
			sk := formatMapKey(k)
			sv := opts.WithTypeMode(elideType).FormatValue(v.MapIndex(k), m)
			list = append(list, textRecord{Key: sk, Value: sv})
		}
		if opts.PrintAddresses {
			ptr = formatPointer(v)
		}
		return textWrap{ptr + "{", list, "}"}
	case reflect.Ptr:
		if v.IsNil() {
			return textNil
		}
		if m.Visit(v) || opts.ShallowPointers {
			return textLine(formatPointer(v))
		}
		if opts.PrintAddresses {
			ptr = formatPointer(v)
		}
		skipType = true  
		return textWrap{"&" + ptr, opts.FormatValue(v.Elem(), m), ""}
	case reflect.Interface:
		if v.IsNil() {
			return textNil
		}
		skipType = true  
		return opts.WithTypeMode(emitType).FormatValue(v.Elem(), m)
	default:
		panic(fmt.Sprintf("%v kind not handled", v.Kind()))
	}
}