文档章节

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======

© 著作权归作者所有

共有 人打赏支持
秋风醉了
粉丝 239
博文 573
码字总数 417084
作品 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
115
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
算法优化|梯度下降和随机梯度下降 — 从0开始

-欢迎加入AI技术专家社群>> - 日薪5K-10K招兼职AI讲师>> 在之前的教程里,我们通过损失函数L中参数的梯度∇θ∇θL来决定如何更新模型θθ的参数。我们也提到过学习率ηη,并给出了使用...

cygqjbabx875u
2017/12/26
0
0
JQuery属性与样式——.att()和.removeAttr()

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

拉考的考拉
2017/11/13
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Linux学习-1031(rsync同步工具 上)

10.28 rsync工具介绍 10.29/10.30 rsync常用选项 10.31 rsync通过ssh同步 一、 rsync工具介绍 rsync是一个同步工具,在日常的运维中常会用到。它可以本地同步,也实现可以远程两台机器同步。...

wxy丶
26分钟前
1
0
python实战一期:第一天

1. 为什么学习python 1.1 为什么要学Python? Python第一是个非常牛B的脚本语言,能满足绝大部分自动化运维的需求,又能做后端C/S架构,又能用WEB框架快速开发出高大上的Web界面,只有当你自...

laoba
28分钟前
2
0
Java并发编程学习三:线程同步的关键字以及理解

上篇文章中介绍了Java线程的带来的问题与内存模型中介绍了线程可能会引发的问题以及对应Java的内存模型,顺带介绍了Volatile和Sychronized关键字。今天对Java中涉及到的常见的关键类和关键字...

JerryLin123
35分钟前
0
0
我用代码来给你们分析一个赚钱的技巧

赚钱是个俗气的话题,但又是人人都绕不开的事情。我今天来“科学”地触碰下这个话题。 谈赚钱,就会谈到理财、投资,谈到炒股。有这样一个笑话: 问:如何成为百万富翁? 答:带一千万进入股...

crossin
35分钟前
1
0
spring MatchingBean应用

1、编写接口FactoryList import java.util.List;public interface FactoryList<E extends MatchingBean<K>, K> extends List<E> { E getBean(K factor); List<E> getBeanLi......

重城重楼
48分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部