package float import ( "strconv" "strings" ) func split(s string, n int) (ret []string) { var pos int if rest := len(s) % n; rest > 0 { ret = append(ret, s[:rest]) pos = rest } for pos < len(s) { ret = append(ret, s[pos:pos+n]) pos += n } return ret } func fill(s string, n int) string { if len(s) >= n { return s[:n] } return s + strings.Repeat("0", n-len(s)) } // Country settings type Country struct { Thousend, Decimal rune // delimiter rune Block, Fraction int // block length } const ( Space = ' ' Apostrophe = '\'' Comma = ',' FullStop = '.' MiddleDot = '\u00b7' ThinSpace = '\u2009' NoBreakSpace = '\u202f' DotAbove = '\u02d9' ) var ( EN = Country{Space, FullStop, 3, 2} // SI EN FR = Country{Space, Comma, 3, 2} // SI FR US = Country{Comma, FullStop, 3, 2} DE = Country{FullStop, Comma, 3, 2} IR = Country{Space, MiddleDot, 3, 2} CH = Country{Apostrophe, FullStop, 3, 2} IT = Country{DotAbove, Comma, 3, 2} CN = Country{Comma, FullStop, 4, 2} // 10000 based ) // DefaultFormat is europeian SI format var DefaultFormat = FR // Format float value as localized representation func (c Country) Format(v float64) string { s := strconv.FormatFloat(v, 'f', -1, 64) neg := strings.HasPrefix(s, "-") if neg { s = s[1:] } parts := strings.Split(s, ".") if len(parts) == 1 { parts = append(parts, "") } lhs := split(parts[0], c.Block) rhs := fill(parts[1], c.Fraction) s = strings.Join(lhs, string(c.Thousend)) if neg { s = "-" + s } return s + string(c.Decimal) + rhs } // Format float with default format func Format(v float64) string { return DefaultFormat.Format(v) }