0. 前言

小白学标准库之反射 reflect 篇中介绍了反射的三大法则。但并未给出具体示例介绍反射,感觉还是少了点什么。这里进一步通过fmt.Println 源码,查看反射如何使用的,算是对前文的补充。由于文章已经够长了,为方便观看,新开一篇介绍,当然内容不会太多。

1. fmt.Println 函数

go 中 Print 系列函数(fmt.Println, fmt.Printf...) 可以打印任意类型,这是怎么做到的呢?结合前面学习我们知道通过反射能够在运行时获取类型值。

查看 fmt.Println 函数实现:

func Println(a ...interface{}) (n int, err error) {
return Fprintln(os.Stdout, a...)
} func Fprintln(w io.Writer, a ...interface{}) (n int, err error) {
p := newPrinter()
p.doPrintln(a)
n, err = w.Write(p.buf)
p.free()
return
}

Println 调用 Fprintln 函数,Fprintln 首先 new 一个 Printer p,接着通过 p 执行 doPrintln:

func (p *pp) doPrintln(a []interface{}) {
for argNum, arg := range a {
if argNum > 0 {
p.buf.writeByte(' ')
}
p.printArg(arg, 'v')
}
p.buf.writeByte('\n')
}

doPrintln 首先解析参数,接着处理参数。重点放在 printArg 这里:

// Some types can be done without reflection.
switch f := arg.(type) {
case bool:
p.fmtBool(f, verb)
case float32:
p.fmtFloat(float64(f), 32, verb)
... case reflect.Value:
// Handle extractable values with special methods
// since printValue does not handle them at depth 0.
if f.IsValid() && f.CanInterface() {
p.arg = f.Interface()
if p.handleMethods(verb) {
return
}
}
p.printValue(f, verb, 0)
default:
// If the type is not simple, it might have methods.
if !p.handleMethods(verb) {
// Need to use reflection, since the type had no
// interface methods that could be used for formatting.
p.printValue(reflect.ValueOf(f), verb, 0)
}
}

doPrintln 函数内容较多,这里摘出重要部分进行介绍。

首先,通过类型断言判断接口值,如果判断不出来则走到 default 分支(这也和 小白学标准库之反射 开篇介绍的对应,即类型断言的表示能力有限,更复杂的表达能力需要通过反射),通过反射机制反射接口值。

如当打印结构体时,分支判断会走到 default,通过反射获取结构体的值:

func main() {
a := person{
name: "lubanseven",
} fmt.Println(a)
}

这里有几点注意的是:

  1. p.printValue 函数是对反射代码在运行时的处理,相比于直接处理,更加复杂,读写都不容易。这也是在静态语言中使用动态特性付出的成本。关于反射代码在运行时的写法可参考 这里
  2. 不管是 小白学标准库之反射 reflect 还是这篇文章都没有介绍汇编,因为汇编是在编译阶段确定的,而反射的实现是在运行时,通过汇编能看到的是 CALL xxx.Println(SB),无法看到具体运行时的实现。

go Print 和 反射的更多相关文章

  1. day7_subprocess模块和面向对象,反射

    常用subprocess方法示例 #执行命令,返回命令执行状态 , 0 or 非0>>> retcode = subprocess.call(["ls", &qu ...

  2. Python全栈--9 __import__ 反射和面向对象基础 self 封装 继承(多继承的顺序) 多态

    一.反射 python中的反射功能是由以下四个内置函数提供:hasattr.getattr.setattr.delattr,改四个函数分别用于对对象内部执行:检查是否含有某成员.获取成员.设置成员.删 ...

  3. Python:time模块&序列化&生成随机数&反射

    time模块:>>> import time >>> time.time <built-in function time> >>> t ...

  4. Day6 反射、模块、正则表达式和算法

    递归完成阶乘 def func(num): if num == 1: return 1 return num * func(num - 1) x = func(7) print(x) 反射 commo ...

  5. day27:反射和双下方法

    1, # 面向对象的三大特性:继承,多态和封装 # 继承: # 单继承: **** # 父类(超类,基类) # 子类(派生类) 派生方法和派生属性 # 子类的对象在调用方法和属性:先用自己的,自己没有 ...

  6. python反射和面向对象的知识并简述基本的异常

    # 1.面向对象不是所有的情况都适用# 2.面向对象编程# a.定义类# class Foo:# def 方法1(self,bb):# b.根据类创建对象(创建) # class Person():# ...

  7. python day21 ——面向对像-反射 getattr,内置方法

    一.反射:用字符串数据类型的变量名来访问这个变量的值 上代码^_^ # class Student: # ROLE = 'STUDENT' # @classmethod # def check_cou ...

  8. python面向对象 : 反射和内置方法

    一. 反射 1. isinstance()和issubclass() isinstance( 对象名, 类名) : 判断对象所属关系,包括父类  (注:type(对象名) is 类名 : 判断对象所属 ...

  9. isinstance、issubclass、反射

    一.isinstance.issubclass # isinstance(obj, cls) 检查obj是否是cls的对象 class A(object):pass a = A() print(isi ...

  10. java中用反射访问私有方法和私有成员[转]

    转自: http://zhouyangchenrui.iteye.com/blog/470521 java的反射可以绕过访问权限,访问到类的私有方法和成员.可能这点会引起安全性的讨论.反射的使用帮助解 ...

随机推荐

  1. gridlayout

    <?xml version="1.0" encoding="utf-8"?> <GridLayout xmlns:android=" ...

  2. Javascript Ajax总结——其他跨域技术之Comet

    Comet指一种更高级的Ajax技术( 也称 "服务器推送" ),一种服务器向页面推送数据的技术.Comet能够让信息近乎实时地被推送到页面上,非常适合体育比赛的分数和股票报价.有 ...

  3. C#设计模式之享元模式(Flyweight)

    using System; using System.Collections; public class Client { public static void Main(string[] args) ...

  4. 聊聊流式数据湖Paimon(四)

    Partial Update 数据打宽 通过不同的流写不同的字段,打宽了数据的维度,填充了数据内容:如下所示: --FlinkSQL参数设置 set `table.dynamic-table-opti ...

  5. 解决C#连接MySQL数据库报错 MySqlConnector

    如果主机不支持 SSL 连接,则不会使用 SSL 连接. 连接不上. 解决方案:在连接字符串后添加 sslmode = none. <add key="connstring" ...

  6. CentOS7部署后优化配置

    1.安装必要的组件.升级 yum -y install wget vim cd /etc/yum.repos.d/ rm -rf /etc/yum.repos.d/*.repo wget http:/ ...

  7. GOF23--23种设计模式(二)

    一.建造者模式 建造者模式也是属于建造型模式,它提供了一种创建对象的最佳方式 定义:将一个复杂的对象的构建和它的表示分离,使得同样的构建过程可以创建不同的表示 主要作用:在用户不知道对象的构建细节的情 ...

  8. Programming Abstractions in C阅读笔记:p246-p247

    <Programming Abstractions in C>学习第68天,p246-p247总结,总计2页. 一.技术总结 本章通过"the game of nim(尼姆游戏) ...

  9. CodeForces 1459C 数论 GCD

    CodeForces 1459C 数论 GCD 原题链接 题意 首先给出n个数 之后给出m个数,每次问之前的n个数加上当前的这个数之后,总体的gcd是多少,也就是答案需要求出m个总体的gcd 思路 因 ...

  10. 云图说|分钟级构建业务大屏——Astro大屏应用

    本文分享自华为云社区<[云图说]第271期 Astro Canvas一站式数据可视化开发,分钟级构建业务大屏>,作者:阅识风云 . Astro大屏应用(Astro Canvas)是Astr ...