You are an expert in writing code in many different languages. Your goal is to perform code completion for the following code, keeping in mind the rest of the code and the file meta data.
    Metadata details:
    filename: ifaddr.go
    path of file: ./repos/teller/vendor/github.com/hashicorp/go-sockaddr
    
    the code of the file until where you have to start completion: package sockaddr

import "strings"

// ifAddrAttrMap is a map of the IfAddr type-specific attributes.
var ifAddrAttrMap map[AttrName]func(IfAddr) string
var ifAddrAttrs []AttrName

func init() {
	ifAddrAttrInit()
}

// GetPrivateIP returns a string with a single IP address that is part of RFC
// 6890 and has a default route.  If the system can't determine its IP address
// or find an RFC 6890 IP address, an empty string will be returned i
    
func GetPrivateIPs() (string, error) {
	ifAddrs, err := GetAllInterfaces()
	if err != nil {
		return "", err
	} else if len(ifAddrs) < 1 {
		return "", nil
	}

	ifAddrs, _ = FilterIfByType(ifAddrs, TypeIP)
	if len(ifAddrs) == 0 {
		return "", nil
	}

	OrderedIfAddrBy(AscIfType, AscIfNetworkSize).Sort(ifAddrs)

	ifAddrs, _, err = IfByRFC("6890", ifAddrs)
	if err != nil {
		return "", err
	} else if len(ifAddrs) == 0 {
		return "", nil
	}

	_, ifAddrs, err = IfByRFC(ForwardingBlacklistRFC, ifAddrs)
	if err != nil {
		return "", err
	} else if len(ifAddrs) == 0 {
		return "", nil
	}

	ips := make([]string, 0, len(ifAddrs))
	for _, ifAddr := range ifAddrs {
		ip := *ToIPAddr(ifAddr.SockAddr)
		s := ip.NetIP().String()
		ips = append(ips, s)
	}

	return strings.Join(ips, " "), nil
}