flag 中的 Go 函数指针

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

内容简介:在阅读 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 包中的代码片段就留给大家自己思考了。


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

查看所有标签

猜你喜欢:

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

PHP高级开发技术与应用

PHP高级开发技术与应用

曹铁群、孙一江、张永学 / 清华大学出版社 / 2002-5-1 / 32.00

作为一本介绍PHP高级开发技术的书籍,本书并不像一般介绍PHP语言的书籍那样讲述大量的语法规则,罗列大量的函数,而是着眼于PHP在Web中的实际应用,特别是PHP对最新技术的支持,比如WAP技术、XML技术等。 本书涉及到的内容主要有:高级环境配置、高级语法和应用、正则表达式、面向对象技术、高级图像技术、用PHPLIB实现模板的处理、用PHPDoc实现文档的自动生成、PHP与组件技术、PH......一起来看看 《PHP高级开发技术与应用》 这本书的介绍吧!

在线进制转换器
在线进制转换器

各进制数互转换器

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具