t.Errorf("expected %q; got %q", expect, err)
        }
 }
+
+func funcNameTestFunc() int {
+       return 0
+}
+
+func TestGoodFuncNames(t *testing.T) {
+       names := []string{
+               "_",
+               "a",
+               "a1",
+               "a1",
+               "Ӵ",
+       }
+       for _, name := range names {
+               tmpl := New("X").Funcs(
+                       FuncMap{
+                               name: funcNameTestFunc,
+                       },
+               )
+               if tmpl == nil {
+                       t.Fatalf("nil result for %q", name)
+               }
+       }
+}
+
+func TestBadFuncNames(t *testing.T) {
+       names := []string{
+               "",
+               "2",
+               "a-b",
+       }
+       for _, name := range names {
+               testBadFuncName(name, t)
+       }
+}
+
+func testBadFuncName(name string, t *testing.T) {
+       defer func() {
+               recover()
+       }()
+       New("X").Funcs(
+               FuncMap{
+                       name: funcNameTestFunc,
+               },
+       )
+       // If we get here, the name did not cause a panic, which is how Funcs
+       // reports an error.
+       t.Errorf("%q succeeded incorrectly as function name", name)
+}
 
 // addValueFuncs adds to values the functions in funcs, converting them to reflect.Values.
 func addValueFuncs(out map[string]reflect.Value, in FuncMap) {
        for name, fn := range in {
+               if !goodName(name) {
+                       panic(fmt.Errorf("function name %s is not a valid identifier", name))
+               }
                v := reflect.ValueOf(fn)
                if v.Kind() != reflect.Func {
                        panic("value for " + name + " not a function")
        }
 }
 
-// goodFunc checks that the function or method has the right result signature.
+// goodFunc reports whether the function or method has the right result signature.
 func goodFunc(typ reflect.Type) bool {
        // We allow functions with 1 result or 2 results where the second is an error.
        switch {
        return false
 }
 
+// goodName reports whether the function name is a valid identifier.
+func goodName(name string) bool {
+       if name == "" {
+               return false
+       }
+       for i, r := range name {
+               switch {
+               case r == '_':
+               case i == 0 && !unicode.IsLetter(r):
+                       return false
+               case !unicode.IsLetter(r) && !unicode.IsDigit(r):
+                       return false
+               }
+       }
+       return true
+}
+
 // findFunction looks for a function in the template, and global map.
 func findFunction(name string, tmpl *Template) (reflect.Value, bool) {
        if tmpl != nil && tmpl.common != nil {
 
 
 // Funcs adds the elements of the argument map to the template's function map.
 // It panics if a value in the map is not a function with appropriate return
-// type. However, it is legal to overwrite elements of the map. The return
-// value is the template, so calls can be chained.
+// type or if the name cannot be used syntactically as a function in a template.
+// It is legal to overwrite elements of the map. The return value is the template,
+// so calls can be chained.
 func (t *Template) Funcs(funcMap FuncMap) *Template {
        t.init()
        t.muFuncs.Lock()