内容简介:在阅读 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 变量的地址。
不带包装
不带包装时的输出如下:
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 包中的代码片段就留给大家自己思考了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- python(函数指针和类函数指针)
- 将数组和矩阵传递给函数,作为C中指针的指针和指针
- C/C++ 函数指针
- CGO 中传递回调函数和指针
- GOLAMG-5 type 不同于C/C++ typedef,切片底层是指针域的函数指针
- Java 8函数式编程模式:不要使用空指针null
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
HTML5与CSS3权威指南(上册) (第3版)
陆凌牛 / 机械工业出版社 / 2015-9-1 / CNY 89.00
本书是HTML 5与CSS 3领域公认的标杆之作,被读者誉为“系统学习HTML 5与CSS 3的最佳著作”和“Web前端工程师案头必备图书之_”。 前两版累计印刷超过15次,网络书店评论超过8000条,98%以上的评论都是五星级的好评。不仅是HTML 5与CSS 3图书领域当之无愧的领头羊,而且在整个原创计算机图书领域是佼佼者。 第3版首先从技术的角度根据最新的HTML 5和CSS 3......一起来看看 《HTML5与CSS3权威指南(上册) (第3版)》 这本书的介绍吧!