文档章节

Go函数值 && 方法值

秋风醉了
 秋风醉了
发布于 2016/07/11 19:25
字数 649
阅读 53
收藏 0

Go函数值 && 方法值

函数值

在Go中,函数被看作第一类值(first-class values):函数像其他值一样,拥有类型,可以被赋值给其他变量,传递给函数,从函数返回。例子如下:

package main

import (
	"fmt"
)

func main() {
	f := square       //把 square 赋值给 f
	fmt.Println(f(3)) // "9"

	f = negative
	fmt.Println(f(3))     // "-3"
	fmt.Printf("%T\n", f) // f 的类型是 "func(int) int"

	// 类型不同,无法赋值
	// f = product // cannot use product (type func(int, int) int) as type func(int) int in assignment

	var ff func(int) int
	if ff != nil { //函数的值 可以和 nil 比较 ,但是函数值之间是不可比较的,也不能用函数值作为map的key。
		ff(3)
	}

	fff := sum(1, 2)
	res := fff(2)

	fmt.Println(res)        // 6
	fmt.Printf("%T\n", fff) // func(int) int

	res2 := sum(1, 2)(2) // 可以这样链式调用,函数 sum 是一个高阶函数
	fmt.Println(res2)    // 6

	////////////////函数作为参数////////////////
	var f1 func(int) int //声明一个函数类型的变量
	//初始化
	f1 = func(a int) int {
		return a * 2
	}

	res3 := sumF(f1)(4, 5) // 链式调用
	fmt.Println(res3)      // 18

	// sumF 的类型
	fmt.Printf("%T\n", sumF) // func(func(int) int) func(int, int) int
}

func square(n int) int     { return n * n }
func negative(n int) int   { return -n }
func product(m, n int) int { return m * n }

// 函数作为返回值

// go 不允许函数嵌套,可以使用把匿名函数赋值给一个变量
func sum(a, b int) func(int) int {

	x := a + b

	temp := func(factor int) (res int) {
		return x * factor
	}

	return temp
}

// 函数作为参数
func sumF(f func(int) int) func(int, int) int {
	return func(a, b int) int {
		if a > b {
			return 0
		} else {
			return f(a + b)
		}
	}
}

方法值和方法表达式

https://docs.ruanjiadeng.com/gopl-zh/ch6/ch6-04.html

这块比较绕,对照着程序运行结果也可以猜个差不多。

package main

import (
	"fmt"
	"math"
)

func main() {

	p := Point{1, 2}
	q := Point{4, 6}

	/*
	   distanceFromP
	   scaleP
	   都是方法值
	*/

	// p.Distance叫作“选择器”,选择器会返回一个方法"值"
	distanceFromP := p.Distance   // method value
	fmt.Println(distanceFromP(q)) // "5"

	var origin Point                   // {0, 0}
	fmt.Println(distanceFromP(origin)) // "2.23606797749979"

	scaleP := p.ScaleBy // method value
	scaleP(2)           // p becomes (2, 4)

	fmt.Println(p)

	fmt.Println(distanceFromP(origin)) // "2.23606797749979"
	fmt.Println(p.Distance(origin))    // "4.47213595499958"

	fmt.Printf("%T\n", distanceFromP) //方法的类型:func(main.Point) float64
	fmt.Printf("%T\n", scaleP)        //方法的类型:func(float64)

	////////////////////////////////
	////  方法表达式
	////////////////////////////////
	distance := Point.Distance // method expression
	fmt.Println(distance(p, q))
	fmt.Printf("%T\n", distance) // "func(Point, Point) float64"

	scale := (*Point).ScaleBy
	scale(&p, 2)
	fmt.Println(p)
	fmt.Printf("%T\n", scale) // "func(*Point, float64)"
}

type Point struct{ X, Y float64 }

// same thing, but as a method of the Point type
func (p Point) Distance(q Point) float64 {
	return math.Hypot(q.X-p.X, q.Y-p.Y)
}

// 指针对象的方法
// 这个方法的名字是(*Point).ScaleBy。这里的括号是必须的;没有括号的话这个表达式可能会被理解为*(Point.ScaleBy)。
func (p *Point) ScaleBy(factor float64) {
	p.X *= factor
	p.Y *= factor
}

======END======

© 著作权归作者所有

共有 人打赏支持
秋风醉了
粉丝 241
博文 566
码字总数 417505
作品 0
朝阳
程序员
私信 提问
【翻译】Go 1.1 函数调用

Go 1.0 版本的 runtime 使用动态代码生成来实现闭包。我认为这样一点也不方便:它避免了修改工具链宽来表达函数的值与函数调用惯例。然而,自从它限制了 Go 可以运行的环境,这就很明显地警示...

无闻
2013/08/02
0
11
NSGA2代码分析——dominance.c

该源文件中包含一个函数int check_dominance (individual *a, individual *b), 主要功能是比较两个个体的支配关系,该函数有三个返回值:0——两个体不可比较支配关系;1——a个体支配b;-...

长平狐
2012/09/20
125
0
为什么 (obj.foo)() 调用的执行环境中的 this 就是 obj ?

首先,看一段代码: var obj = {foo: function() { }} 用不同的方式调用obj的foo方法有不同的结果: obj.foo(); // this is obj !(obj.foo)(); // this is obj !(0 || obj.foo)(); // this ......

呵呵闯
2016/08/14
19
0
JQuery属性与样式——.att()和.removeAttr()

1 每个元素都有一个或多个特性,用途是给出相应元素或者其内容的附加信息,如:在img元素中,src就是元素的特性,用来标记图片的地址 2 操作特性的主要DOM方法 getAttribute方法 setAttribu...

拉考的考拉
2017/11/13
0
0
jQuery批量修改Name值,批量增加name后缀,非each(不需要循环)

背景 表单字段,配置where属性自动刷新到可查询区域,查询字段需增加_where后缀,响应后台规则 问题 批量设置的查询字段,必须批量增加_where后缀方可正常查询。each循环有点麻烦,有没有更方...

沫沫金
2017/09/18
0
0

没有更多内容

加载失败,请刷新页面

加载更多

centos7重置密码、单用户模式、救援模式、ls命令、chmod命令

在工作当中如果我们错误的配置了文件使服务器不能正常启动或者忘记密码不能登录系统,如何解决这些问题呢?重装系统是可以实现的,但是往往不能轻易重装系统的,下面用忘记密码作为例子讲解如...

李超小牛子
今天
3
0
Python如何开发桌面应用程序?Python基础教程,第十三讲,图形界面

当使用桌面应用程序的时候,有没有那么一瞬间,想学习一下桌面应用程序开发?行业内专业的桌面应用程序开发一般是C++,C#来做,Java开发的也有,但是比较少。本节课会介绍Python的GUI(图形用...

程序员补给栈
今天
5
0
kafka在的使用

一、基本概念 介绍 Kafka是一个分布式的、可分区的、可复制的消息系统。它提供了普通消息系统的功能,但具有自己独特的设计。 这个独特的设计是什么样的呢? 首先让我们看几个基本的消息系统...

狼王黄师傅
今天
3
0
Android JNI总结

0x01 JNI介绍 JNI是Java Native Interface的缩写,JNI不是Android专有的东西,它是从Java继承而来,但是在Android中,JNI的作用和重要性大大增强。 JNI在Android中起着连接Java和C/C++层的作...

天王盖地虎626
昨天
3
0
大数据教程(11.8)Hive1.2.2简介&初体验

上一篇文章分析了Hive1.2.2的安装,本节博主将分享Hive的体验&Hive服务端和客户端的使用方法。 一、Hive与hadoop直接的关系 Hive利用HDFS存储数据,利用MapReduce查询数据。 二、Hive与传统数...

em_aaron
昨天
4
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部