GO的函数类型

93 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第9天,点击查看活动详情

函数字面量类型和函数命名类型
函数字面量类型:

通常我们可以见到“匿名函数“这个概念,与之相对应的是”有名函数“,这两种类型都属于函数字面量类型,只不过一个是绑定了函数名变量,一个没有绑定。 有名函数格式:func funcName(InputTypeList) OutPutTypeList 匿名函数格式:func (InputTypeList) OutPutTypeList 函数字面量类型:func (InputTypeList) OutPutTypeList

所以直观上来看,匿名函数是直接初始化了一个函数字面量类型,而有名函数不仅初始化了而且还将其赋给了一个函数名变量。 如:


//方法声明 = 方法名 + 方法签名(其实就是函数字面量类型)
func add(a,b int) int {  //func (int, int)int是函数字面量类型
	return a+b
}
函数命名类型:
Type NewFuncType FuncLiteral

type Add func (int, int) int

此时Add的函数命名类型是func (int, int) int,当然此时我们没有函数的处理逻辑。记住上面讲过函数声明时函数的字面量类型也是func (int, int)int。所以我们完全可以将add赋值给Add。

var Add = add
HTTP源码示例

查看http的server标准库Go代码,可以看出函数类型的精妙用法。

type HandlerFunc func(ResponseWriter, *Request)
//函数命名类型为 func(ResponseWriter, *Request) 没有返回值

// ServeHTTP calls f(w, r).
//为函数添加方法!!!!是一种装饰设计模式
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
	f(w, r)
}

//HandleFunc实现了Hadler接口的方法
type Handler interface {
	ServeHTTP(ResponseWriter, *Request)
}

//Handle参数列表中有接口变量
func (mux *ServeMux) Handle(pattern string, handler Handler) {
	mux.mu.Lock()
	defer mux.mu.Unlock()

	if pattern == "" {
		panic("http: invalid pattern")
	}
	if handler == nil {
		panic("http: nil handler")
	}
	if _, exist := mux.m[pattern]; exist {
		panic("http: multiple registrations for " + pattern)
	}

	if mux.m == nil {
		mux.m = make(map[string]muxEntry)
	}
	e := muxEntry{h: handler, pattern: pattern}
	mux.m[pattern] = e
	if pattern[len(pattern)-1] == '/' {
		mux.es = appendSorted(mux.es, e)
	}

	if pattern[0] != '/' {
		mux.hosts = true
	}
}

// HandleFunc registers the handler function for the given pattern.
// HandleFunc 类型的变量可以传递给Handler接口变量
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
	if handler == nil {
		panic("http: nil handler")
	}
	mux.Handle(pattern, HandlerFunc(handler))
}
总结
  1. 有名函数和匿名函数的函数字面量类型和函数命名类型相同,可以相互转换
  2. 函数也可以添加方法,为一个函数增加额外的小功能
  3. 函数添加方法实现接口,使得函数能够转换到接口
  4. 函数声明 = 函数名 + 函数字面量类型