diff --git a/src/pkg/text/template/doc.go b/src/pkg/text/template/doc.go index ab18f9ab1a6..f622ac7dcee 100644 --- a/src/pkg/text/template/doc.go +++ b/src/pkg/text/template/doc.go @@ -326,13 +326,22 @@ functions: ge Returns the boolean truth of arg1 >= arg2 -These functions work on basic types only (or named basic types, -such as "type Celsius float32"). They implement the Go rules for -comparison of values, except that size and exact type are ignored, -so any integer value may be compared with any other integer value, -any unsigned integer value may be compared with any other unsigned -integer value, and so on. However, as usual, one may not compare -an int with a float32 and so on. +For simpler multi-way equality tests, eq (only) accepts two or more +arguments and compares the second and subsequent to the first, +returning in effect + + arg1==arg2 || arg1==arg3 || arg1==arg4 ... + +(Unlike with || in Go, however, eq is a function call and all the +arguments will be evaluated.) + +The comparison functions work on basic types only (or named basic +types, such as "type Celsius float32"). They implement the Go rules +for comparison of values, except that size and exact type are +ignored, so any integer value may be compared with any other integer +value, any unsigned integer value may be compared with any other +unsigned integer value, and so on. However, as usual, one may not +compare an int with a float32 and so on. Associated templates diff --git a/src/pkg/text/template/exec_test.go b/src/pkg/text/template/exec_test.go index bc8aee6f3cc..f60702de8f1 100644 --- a/src/pkg/text/template/exec_test.go +++ b/src/pkg/text/template/exec_test.go @@ -891,6 +891,8 @@ var cmpTests = []cmpTest{ {"eq `xy` `xyz`", "false", true}, {"eq .Xuint .Xuint", "true", true}, {"eq .Xuint .Yuint", "false", true}, + {"eq 3 4 5 6 3", "true", true}, + {"eq 3 4 5 6 7", "false", true}, {"ne true true", "false", true}, {"ne true false", "true", true}, {"ne 1+2i 1+2i", "false", true}, @@ -946,7 +948,6 @@ var cmpTests = []cmpTest{ {"ge .Xuint .Yuint", "false", true}, {"ge .Yuint .Xuint", "true", true}, // Errors - {"eq 3 4 5", "", false}, // Too many arguments. {"eq `xy` 1", "", false}, // Different types. {"lt true true", "", false}, // Unordered types. {"lt 1+0i 1+0i", "", false}, // Unordered types. @@ -970,7 +971,7 @@ func TestComparison(t *testing.T) { continue } if !test.ok && err == nil { - t.Errorf("%s did not error") + t.Errorf("%s did not error", test.expr) continue } if b.String() != test.truth { diff --git a/src/pkg/text/template/funcs.go b/src/pkg/text/template/funcs.go index 63287085aa4..e854122624e 100644 --- a/src/pkg/text/template/funcs.go +++ b/src/pkg/text/template/funcs.go @@ -264,6 +264,7 @@ func not(arg interface{}) (truth bool) { var ( errBadComparisonType = errors.New("invalid type for comparison") errBadComparison = errors.New("incompatible types for comparison") + errNoComparison = errors.New("missing argument for comparison") ) type kind int @@ -297,39 +298,47 @@ func basicKind(v reflect.Value) (kind, error) { return invalidKind, errBadComparisonType } -// eq evaluates the comparison a == b. -func eq(arg1, arg2 interface{}) (bool, error) { +// eq evaluates the comparison a == b || a == c || ... +func eq(arg1 interface{}, arg2 ...interface{}) (bool, error) { v1 := reflect.ValueOf(arg1) k1, err := basicKind(v1) if err != nil { return false, err } - v2 := reflect.ValueOf(arg2) - k2, err := basicKind(v2) - if err != nil { - return false, err + if len(arg2) == 0 { + return false, errNoComparison } - if k1 != k2 { - return false, errBadComparison + for _, arg := range arg2 { + v2 := reflect.ValueOf(arg) + k2, err := basicKind(v2) + if err != nil { + return false, err + } + if k1 != k2 { + return false, errBadComparison + } + truth := false + switch k1 { + case boolKind: + truth = v1.Bool() == v2.Bool() + case complexKind: + truth = v1.Complex() == v2.Complex() + case floatKind: + truth = v1.Float() == v2.Float() + case intKind: + truth = v1.Int() == v2.Int() + case stringKind: + truth = v1.String() == v2.String() + case uintKind: + truth = v1.Uint() == v2.Uint() + default: + panic("invalid kind") + } + if truth { + return true, nil + } } - truth := false - switch k1 { - case boolKind: - truth = v1.Bool() == v2.Bool() - case complexKind: - truth = v1.Complex() == v2.Complex() - case floatKind: - truth = v1.Float() == v2.Float() - case intKind: - truth = v1.Int() == v2.Int() - case stringKind: - truth = v1.String() == v2.String() - case uintKind: - truth = v1.Uint() == v2.Uint() - default: - panic("invalid kind") - } - return truth, nil + return false, nil } // ne evaluates the comparison a != b.