flag 中的 Go 函数指针

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

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


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

查看所有标签

猜你喜欢:

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

Parsing Techniques

Parsing Techniques

Dick Grune、Ceriel J.H. Jacobs / Springer / 2010-2-12 / USD 109.00

This second edition of Grune and Jacobs' brilliant work presents new developments and discoveries that have been made in the field. Parsing, also referred to as syntax analysis, has been and continues......一起来看看 《Parsing Techniques》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具