flag 中的 Go 函数指针

栏目: C · 发布时间: 7年前

内容简介:在阅读 flag 包的代码时,看到一处对函数指针的精妙用法。在这里想和大家分享一下。废话不多说,我们直接上代码。如果上面的代码不清楚含义,请阅读之前讲解 flag 包的文章。

在阅读 flag 包的代码时,看到一处对函数指针的精妙用法。在这里想和大家分享一下。

引出问题

废话不多说,我们直接上代码。

var CommandLine = NewFlagSet(os.Args[0], ExitOnError)

func init() {
	CommandLine.Usage = commandLineUsage
}

func commandLineUsage() {
	Usage()
}

var Usage = func() {
	fmt.Fprintf(CommandLine.Output(), "Usage of %s:\n", os.Args[0])
	PrintDefaults()
}

如果上面的代码不清楚含义,请阅读之前讲解 flag 包的文章。

咋一看还真不知道,干了些啥,更不明白为什么要将 Usage() 包一层。

那我们先来看一下下面这段代码。尝试运行一下。删除上面一条语句的注释并注释下面一条语句,再运行一下并对比不同。

package main

import "fmt"

type printer struct {
	print func()
}

var p = &printer{}

var printA = func() {
	println("A")
}

func wrapper() {
	printA()
	fmt.Printf("wrapper printA %p, &printA %p\n", printA, &printA)
}

func init() {
	// p.print = printA
	p.print = wrapper
}

func printB() {
	println("B")
}

func main() {
	fmt.Printf("printA  %p, &printA  %p\n", printA, &printA)
	fmt.Printf("printB  %p\n", printB)
	fmt.Printf("p.print %p, &p.print %p\n", p.print, &p.print)
	fmt.Printf("wrapper %p\n", wrapper)

	printA()
	fmt.Printf("printA  %p, &printA  %p\n", printA, &printA)
	p.print()
	fmt.Printf("p.print %p, &p.print %p\n", p.print, &p.print)

	printA = printB
	printA()
	fmt.Printf("printA  %p, &printA  %p\n", printA, &printA)
	p.print()
	fmt.Printf("p.print %p, &p.print %p\n", p.print, &p.print)
}

现在我们好好对比一下两者到不同。

带有包装

带有包装时的输出如下:

printA  0x1093490, &printA  0x115fd78       # here
printB  0x1092fa0
p.print 0x1092e80, &p.print 0x11666c8
wrapper 0x1092e80                           # here
A
printA  0x1093490, &printA  0x115fd78       # here
A
wrapper printA 0x1093490, &printA 0x115fd78 # here
p.print 0x1092e80, &p.print 0x11666c8
B
printA  0x1092fa0, &printA  0x115fd78       # here
B
wrapper printA 0x1092fa0, &printA 0x115fd78 # here
p.print 0x1092e80, &p.print 0x11666c8

修改 printA 前,printA 变量的地址为 0x115fd78,printA 中所存当函数地址为 0x1093490。

修改 printA 后,printA 中所存当函数地址变成 0x1092fa0。wrapper 中 printA 发生同样当变化。

所以可以得出,wrapper 中所存的是 printA 变量的地址。

flag 中的  <a href='https://www.codercto.com/topics/6127.html'>Go</a>  函数指针

不带包装

不带包装时的输出如下:

printA  0x1093480, &printA  0x115fd78 # here
printB  0x1092f90
p.print 0x1093480, &p.print 0x11666c8 # here
wrapper 0x1092e80
A
printA  0x1093480, &printA  0x115fd78 # here
A
p.print 0x1093480, &p.print 0x11666c8 # here
B
printA  0x1092f90, &printA  0x115fd78 # here
A
p.print 0x1093480, &p.print 0x11666c8 # here

由输出可以得出,p.print 中的存是函数当地址。这也符合 “=” 的本意。将 printA 中的值赋给 p.print。

flag 中的 Go 函数指针

作业

讲了这么多,那关于 flag 包中的代码片段就留给大家自己思考了。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。

算法谜题

算法谜题

Anany Levitin、Maria Levitin / 赵勇、徐章宁、高博 / 人民邮电出版社 / 2014-1-1

算法是计算机科学领域最重要的基石之一。算法谜题,就是能够直接或间接地采用算法来加以解决的谜题。求解算法谜题是培养和锻炼算法思维能力一种最有效和最有乐趣的途径。 本书是一本经典算法谜题的合集。本书包括了一些古已有之的谜题,数学和计算机科学有一部分知识就发源于此。本书中还有一些较新的谜题,其中有一部分谜题被用作知名IT企业的面试题。全书可分为4个部分,分别是概览、谜题、提示和答案。概览介绍了算法......一起来看看 《算法谜题》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

html转js在线工具
html转js在线工具

html转js在线工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换