gopl-zh.github.com/ch12/ch12-09.html
github-actions[bot] 24eb7f8fea deploy: 56bbafbd08
2024-08-13 00:15:53 +00:00

610 lines
31 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE HTML>
<html lang="zh" class="sidebar-visible no-js light">
<head>
<!-- Book generated using https://github.com/wa-lang/wabook -->
<meta charset="UTF-8">
<title>几点忠告 - Go语言圣经</title>
<!-- Custom HTML head -->
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
<meta name="description" content="">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="theme-color" content="#ffffff" />
<link rel="icon" href="../favicon.svg">
<link rel="shortcut icon" href="../favicon.png">
<link rel="stylesheet" href="../static/wabook/css/variables.css">
<link rel="stylesheet" href="../static/wabook/css/general.css">
<link rel="stylesheet" href="../static/wabook/css/chrome.css">
<link rel="stylesheet" href="../static/wabook/css/print.css" media="print">
<!-- Fonts -->
<link rel="stylesheet" href="../static/wabook/FontAwesome/css/font-awesome.css">
<link rel="stylesheet" href="../static/wabook/fonts/fonts.css">
<!-- Highlight.js Stylesheets -->
<link rel="stylesheet" href="../static/wabook/highlight.css">
<link rel="stylesheet" href="../static/wabook/tomorrow-night.css">
<link rel="stylesheet" href="../static/wabook/ayu-highlight.css">
<!-- Custom theme stylesheets -->
</head>
<body>
<!-- Provide site root to javascript -->
<script type="text/javascript">
var path_to_root = "../";
var default_theme = window.matchMedia("(prefers-color-scheme: dark)").matches ? "navy" : "light";
</script>
<!-- Work around some values being stored in localStorage wrapped in quotes -->
<script type="text/javascript">
try {
var theme = localStorage.getItem('wabook-theme');
var sidebar = localStorage.getItem('wabook-sidebar');
if (theme.startsWith('"') && theme.endsWith('"')) {
localStorage.setItem('wabook-theme', theme.slice(1, theme.length - 1));
}
if (sidebar.startsWith('"') && sidebar.endsWith('"')) {
localStorage.setItem('wabook-sidebar', sidebar.slice(1, sidebar.length - 1));
}
} catch (e) { }
</script>
<!-- Set the theme before any content is loaded, prevents flash -->
<script type="text/javascript">
var theme;
try { theme = localStorage.getItem('wabook-theme'); } catch(e) { }
if (theme === null || theme === undefined) { theme = default_theme; }
var html = document.querySelector('html');
html.classList.remove('no-js')
html.classList.remove('light')
html.classList.add(theme);
html.classList.add('js');
</script>
<!-- Hide / unhide sidebar before it is displayed -->
<script type="text/javascript">
var html = document.querySelector('html');
var sidebar = 'hidden';
if (document.body.clientWidth >= 1080) {
try { sidebar = localStorage.getItem('wabook-sidebar'); } catch(e) { }
sidebar = sidebar || 'visible';
}
html.classList.remove('sidebar-visible');
html.classList.add("sidebar-" + sidebar);
</script>
<nav id="sidebar" class="sidebar" aria-label="Table of contents">
<div class="sidebar-scrollbox">
<ol class="chapter">
<li class="chapter-item expanded ">
<a href="../index.html" >Go语言圣经</a>
</li>
<li class="chapter-item expanded ">
<a href="../preface-zh.html" >译者序</a>
</li>
<li class="chapter-item expanded ">
<a href="../preface.html" >前言</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch1/ch1.html" ><strong aria-hidden="true">1.</strong> 入门</a>
</li>
<ol class="section">
<li class="chapter-item expanded ">
<a href="../ch1/ch1-01.html" ><strong aria-hidden="true">1.1.</strong> Hello, World</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch1/ch1-02.html" ><strong aria-hidden="true">1.2.</strong> 命令行参数</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch1/ch1-03.html" ><strong aria-hidden="true">1.3.</strong> 查找重复的行</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch1/ch1-04.html" ><strong aria-hidden="true">1.4.</strong> GIF动画</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch1/ch1-05.html" ><strong aria-hidden="true">1.5.</strong> 获取URL</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch1/ch1-06.html" ><strong aria-hidden="true">1.6.</strong> 并发获取多个URL</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch1/ch1-07.html" ><strong aria-hidden="true">1.7.</strong> Web服务</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch1/ch1-08.html" ><strong aria-hidden="true">1.8.</strong> 本章要点</a>
</li>
</ol>
<li class="chapter-item expanded ">
<a href="../ch2/ch2.html" ><strong aria-hidden="true">2.</strong> 程序结构</a>
</li>
<ol class="section">
<li class="chapter-item expanded ">
<a href="../ch2/ch2-01.html" ><strong aria-hidden="true">2.1.</strong> 命名</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch2/ch2-02.html" ><strong aria-hidden="true">2.2.</strong> 声明</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch2/ch2-03.html" ><strong aria-hidden="true">2.3.</strong> 变量</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch2/ch2-04.html" ><strong aria-hidden="true">2.4.</strong> 赋值</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch2/ch2-05.html" ><strong aria-hidden="true">2.5.</strong> 类型</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch2/ch2-06.html" ><strong aria-hidden="true">2.6.</strong> 包和文件</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch2/ch2-07.html" ><strong aria-hidden="true">2.7.</strong> 作用域</a>
</li>
</ol>
<li class="chapter-item expanded ">
<a href="../ch3/ch3.html" ><strong aria-hidden="true">3.</strong> 基础数据类型</a>
</li>
<ol class="section">
<li class="chapter-item expanded ">
<a href="../ch3/ch3-01.html" ><strong aria-hidden="true">3.1.</strong> 整型</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch3/ch3-02.html" ><strong aria-hidden="true">3.2.</strong> 浮点数</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch3/ch3-03.html" ><strong aria-hidden="true">3.3.</strong> 复数</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch3/ch3-04.html" ><strong aria-hidden="true">3.4.</strong> 布尔型</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch3/ch3-05.html" ><strong aria-hidden="true">3.5.</strong> 字符串</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch3/ch3-06.html" ><strong aria-hidden="true">3.6.</strong> 常量</a>
</li>
</ol>
<li class="chapter-item expanded ">
<a href="../ch4/ch4.html" ><strong aria-hidden="true">4.</strong> 复合数据类型</a>
</li>
<ol class="section">
<li class="chapter-item expanded ">
<a href="../ch4/ch4-01.html" ><strong aria-hidden="true">4.1.</strong> 数组</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch4/ch4-02.html" ><strong aria-hidden="true">4.2.</strong> Slice</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch4/ch4-03.html" ><strong aria-hidden="true">4.3.</strong> Map</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch4/ch4-04.html" ><strong aria-hidden="true">4.4.</strong> 结构体</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch4/ch4-05.html" ><strong aria-hidden="true">4.5.</strong> JSON</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch4/ch4-06.html" ><strong aria-hidden="true">4.6.</strong> 文本和HTML模板</a>
</li>
</ol>
<li class="chapter-item expanded ">
<a href="../ch5/ch5.html" ><strong aria-hidden="true">5.</strong> 函数</a>
</li>
<ol class="section">
<li class="chapter-item expanded ">
<a href="../ch5/ch5-01.html" ><strong aria-hidden="true">5.1.</strong> 函数声明</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch5/ch5-02.html" ><strong aria-hidden="true">5.2.</strong> 递归</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch5/ch5-03.html" ><strong aria-hidden="true">5.3.</strong> 多返回值</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch5/ch5-04.html" ><strong aria-hidden="true">5.4.</strong> 错误</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch5/ch5-05.html" ><strong aria-hidden="true">5.5.</strong> 函数值</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch5/ch5-06.html" ><strong aria-hidden="true">5.6.</strong> 匿名函数</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch5/ch5-07.html" ><strong aria-hidden="true">5.7.</strong> 可变参数</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch5/ch5-08.html" ><strong aria-hidden="true">5.8.</strong> Deferred函数</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch5/ch5-09.html" ><strong aria-hidden="true">5.9.</strong> Panic异常</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch5/ch5-10.html" ><strong aria-hidden="true">5.10.</strong> Recover捕获异常</a>
</li>
</ol>
<li class="chapter-item expanded ">
<a href="../ch6/ch6.html" ><strong aria-hidden="true">6.</strong> 方法</a>
</li>
<ol class="section">
<li class="chapter-item expanded ">
<a href="../ch6/ch6-01.html" ><strong aria-hidden="true">6.1.</strong> 方法声明</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch6/ch6-02.html" ><strong aria-hidden="true">6.2.</strong> 基于指针对象的方法</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch6/ch6-03.html" ><strong aria-hidden="true">6.3.</strong> 通过嵌入结构体来扩展类型</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch6/ch6-04.html" ><strong aria-hidden="true">6.4.</strong> 方法值和方法表达式</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch6/ch6-05.html" ><strong aria-hidden="true">6.5.</strong> 示例: Bit数组</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch6/ch6-06.html" ><strong aria-hidden="true">6.6.</strong> 封装</a>
</li>
</ol>
<li class="chapter-item expanded ">
<a href="../ch7/ch7.html" ><strong aria-hidden="true">7.</strong> 接口</a>
</li>
<ol class="section">
<li class="chapter-item expanded ">
<a href="../ch7/ch7-01.html" ><strong aria-hidden="true">7.1.</strong> 接口是合约</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch7/ch7-02.html" ><strong aria-hidden="true">7.2.</strong> 接口类型</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch7/ch7-03.html" ><strong aria-hidden="true">7.3.</strong> 实现接口的条件</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch7/ch7-04.html" ><strong aria-hidden="true">7.4.</strong> flag.Value接口</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch7/ch7-05.html" ><strong aria-hidden="true">7.5.</strong> 接口值</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch7/ch7-06.html" ><strong aria-hidden="true">7.6.</strong> sort.Interface接口</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch7/ch7-07.html" ><strong aria-hidden="true">7.7.</strong> http.Handler接口</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch7/ch7-08.html" ><strong aria-hidden="true">7.8.</strong> error接口</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch7/ch7-09.html" ><strong aria-hidden="true">7.9.</strong> 示例: 表达式求值</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch7/ch7-10.html" ><strong aria-hidden="true">7.10.</strong> 类型断言</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch7/ch7-11.html" ><strong aria-hidden="true">7.11.</strong> 基于类型断言识别错误类型</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch7/ch7-12.html" ><strong aria-hidden="true">7.12.</strong> 通过类型断言查询接口</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch7/ch7-13.html" ><strong aria-hidden="true">7.13.</strong> 类型分支</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch7/ch7-14.html" ><strong aria-hidden="true">7.14.</strong> 示例: 基于标记的XML解码</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch7/ch7-15.html" ><strong aria-hidden="true">7.15.</strong> 补充几点</a>
</li>
</ol>
<li class="chapter-item expanded ">
<a href="../ch8/ch8.html" ><strong aria-hidden="true">8.</strong> Goroutines和Channels</a>
</li>
<ol class="section">
<li class="chapter-item expanded ">
<a href="../ch8/ch8-01.html" ><strong aria-hidden="true">8.1.</strong> Goroutines</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch8/ch8-02.html" ><strong aria-hidden="true">8.2.</strong> 示例: 并发的Clock服务</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch8/ch8-03.html" ><strong aria-hidden="true">8.3.</strong> 示例: 并发的Echo服务</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch8/ch8-04.html" ><strong aria-hidden="true">8.4.</strong> Channels</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch8/ch8-05.html" ><strong aria-hidden="true">8.5.</strong> 并发的循环</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch8/ch8-06.html" ><strong aria-hidden="true">8.6.</strong> 示例: 并发的Web爬虫</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch8/ch8-07.html" ><strong aria-hidden="true">8.7.</strong> 基于select的多路复用</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch8/ch8-08.html" ><strong aria-hidden="true">8.8.</strong> 示例: 并发的目录遍历</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch8/ch8-09.html" ><strong aria-hidden="true">8.9.</strong> 并发的退出</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch8/ch8-10.html" ><strong aria-hidden="true">8.10.</strong> 示例: 聊天服务</a>
</li>
</ol>
<li class="chapter-item expanded ">
<a href="../ch9/ch9.html" ><strong aria-hidden="true">9.</strong> 基于共享变量的并发</a>
</li>
<ol class="section">
<li class="chapter-item expanded ">
<a href="../ch9/ch9-01.html" ><strong aria-hidden="true">9.1.</strong> 竞争条件</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch9/ch9-02.html" ><strong aria-hidden="true">9.2.</strong> sync.Mutex互斥锁</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch9/ch9-03.html" ><strong aria-hidden="true">9.3.</strong> sync.RWMutex读写锁</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch9/ch9-04.html" ><strong aria-hidden="true">9.4.</strong> 内存同步</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch9/ch9-05.html" ><strong aria-hidden="true">9.5.</strong> sync.Once惰性初始化</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch9/ch9-06.html" ><strong aria-hidden="true">9.6.</strong> 竞争条件检测</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch9/ch9-07.html" ><strong aria-hidden="true">9.7.</strong> 示例: 并发的非阻塞缓存</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch9/ch9-08.html" ><strong aria-hidden="true">9.8.</strong> Goroutines和线程</a>
</li>
</ol>
<li class="chapter-item expanded ">
<a href="../ch10/ch10.html" ><strong aria-hidden="true">10.</strong> 包和工具</a>
</li>
<ol class="section">
<li class="chapter-item expanded ">
<a href="../ch10/ch10-01.html" ><strong aria-hidden="true">10.1.</strong> 包简介</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch10/ch10-02.html" ><strong aria-hidden="true">10.2.</strong> 导入路径</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch10/ch10-03.html" ><strong aria-hidden="true">10.3.</strong> 包声明</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch10/ch10-04.html" ><strong aria-hidden="true">10.4.</strong> 导入声明</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch10/ch10-05.html" ><strong aria-hidden="true">10.5.</strong> 包的匿名导入</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch10/ch10-06.html" ><strong aria-hidden="true">10.6.</strong> 包和命名</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch10/ch10-07.html" ><strong aria-hidden="true">10.7.</strong> 工具</a>
</li>
</ol>
<li class="chapter-item expanded ">
<a href="../ch11/ch11.html" ><strong aria-hidden="true">11.</strong> 测试</a>
</li>
<ol class="section">
<li class="chapter-item expanded ">
<a href="../ch11/ch11-01.html" ><strong aria-hidden="true">11.1.</strong> go test</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch11/ch11-02.html" ><strong aria-hidden="true">11.2.</strong> 测试函数</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch11/ch11-03.html" ><strong aria-hidden="true">11.3.</strong> 测试覆盖率</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch11/ch11-04.html" ><strong aria-hidden="true">11.4.</strong> 基准测试</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch11/ch11-05.html" ><strong aria-hidden="true">11.5.</strong> 剖析</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch11/ch11-06.html" ><strong aria-hidden="true">11.6.</strong> 示例函数</a>
</li>
</ol>
<li class="chapter-item expanded ">
<a href="../ch12/ch12.html" ><strong aria-hidden="true">12.</strong> 反射</a>
</li>
<ol class="section">
<li class="chapter-item expanded ">
<a href="../ch12/ch12-01.html" ><strong aria-hidden="true">12.1.</strong> 为何需要反射?</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch12/ch12-02.html" ><strong aria-hidden="true">12.2.</strong> reflect.Type和reflect.Value</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch12/ch12-03.html" ><strong aria-hidden="true">12.3.</strong> Display递归打印</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch12/ch12-04.html" ><strong aria-hidden="true">12.4.</strong> 示例: 编码S表达式</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch12/ch12-05.html" ><strong aria-hidden="true">12.5.</strong> 通过reflect.Value修改值</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch12/ch12-06.html" ><strong aria-hidden="true">12.6.</strong> 示例: 解码S表达式</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch12/ch12-07.html" ><strong aria-hidden="true">12.7.</strong> 获取结构体字段标签</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch12/ch12-08.html" ><strong aria-hidden="true">12.8.</strong> 显示一个类型的方法集</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch12/ch12-09.html" class="active"><strong aria-hidden="true">12.9.</strong> 几点忠告</a>
</li>
</ol>
<li class="chapter-item expanded ">
<a href="../ch13/ch13.html" ><strong aria-hidden="true">13.</strong> 底层编程</a>
</li>
<ol class="section">
<li class="chapter-item expanded ">
<a href="../ch13/ch13-01.html" ><strong aria-hidden="true">13.1.</strong> unsafe.Sizeof, Alignof 和 Offsetof</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch13/ch13-02.html" ><strong aria-hidden="true">13.2.</strong> unsafe.Pointer</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch13/ch13-03.html" ><strong aria-hidden="true">13.3.</strong> 示例: 深度相等判断</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch13/ch13-04.html" ><strong aria-hidden="true">13.4.</strong> 通过cgo调用C代码</a>
</li>
<li class="chapter-item expanded ">
<a href="../ch13/ch13-05.html" ><strong aria-hidden="true">13.5.</strong> 几点忠告</a>
</li>
</ol>
<li class="chapter-item expanded ">
<a href="../appendix/appendix.html" ><strong aria-hidden="true">14.</strong> 附录</a>
</li>
<ol class="section">
<li class="chapter-item expanded ">
<a href="../appendix/appendix-a-errata.html" ><strong aria-hidden="true">14.1.</strong> 附录A原文勘误</a>
</li>
<li class="chapter-item expanded ">
<a href="../appendix/appendix-b-author.html" ><strong aria-hidden="true">14.2.</strong> 附录B作者译者</a>
</li>
<li class="chapter-item expanded ">
<a href="../appendix/appendix-c-cpoyright.html" ><strong aria-hidden="true">14.3.</strong> 附录C译文授权</a>
</li>
<li class="chapter-item expanded ">
<a href="../appendix/appendix-d-translations.html" ><strong aria-hidden="true">14.4.</strong> 附录D其它语言</a>
</li>
</ol>
</ol>
</div>
<div id="sidebar-resize-handle" class="sidebar-resize-handle"></div>
</nav>
<div id="page-wrapper" class="page-wrapper">
<div class="page">
<div id="menu-bar-hover-placeholder"></div>
<div id="menu-bar" class="menu-bar sticky bordered">
<div class="left-buttons">
<button id="sidebar-toggle" class="icon-button" type="button" title="Toggle Table of Contents" aria-label="Toggle Table of Contents" aria-controls="sidebar">
<i class="fa fa-bars"></i>
</button>
<button id="theme-toggle" class="icon-button" type="button" title="Change theme" aria-label="Change theme" aria-haspopup="true" aria-expanded="false" aria-controls="theme-list">
<i class="fa fa-paint-brush"></i>
</button>
<ul id="theme-list" class="theme-popup" aria-label="Themes" role="menu">
<li role="none"><button role="menuitem" class="theme" id="light">Light (default)</button></li>
<li role="none"><button role="menuitem" class="theme" id="coal">Coal</button></li>
<li role="none"><button role="menuitem" class="theme" id="navy">Navy</button></li>
<li role="none"><button role="menuitem" class="theme" id="ayu">Ayu</button></li>
</ul>
</div>
<h1 class="menu-title"><a href="../index.html">Go语言圣经</a></h1>
<div class="right-buttons">
<a href="https://github.com/gopl-zh/gopl-zh.github.com" title="Git repository" aria-label="Git repository">
<i id="git-repository-button" class="fa fa-github"></i>
</a>
<a href="https://github.com/gopl-zh/gopl-zh.github.com/edit/master/ch12/ch12-09.md" title="Suggest an edit" aria-label="Suggest an edit">
<i id="git-edit-button" class="fa fa-edit"></i>
</a>
</div>
</div>
<!-- Apply ARIA attributes after the sidebar and the sidebar toggle button are added to the DOM -->
<script type="text/javascript">
document.getElementById('sidebar-toggle').setAttribute('aria-expanded', sidebar === 'visible');
document.getElementById('sidebar').setAttribute('aria-hidden', sidebar !== 'visible');
Array.from(document.querySelectorAll('#sidebar a')).forEach(function(link) {
link.setAttribute('tabIndex', sidebar === 'visible' ? 0 : -1);
});
</script>
<div id="content" class="content">
<!-- Page table of contents -->
<div class="sidetoc"><nav class="pagetoc"></nav></div>
<main>
<ul dir="auto"><li><em>凹语言(Go实现, 面向WASM设计): <a href="https://github.com/wa-lang/wa">https://github.com/wa-lang/wa</a></em></li><li><em>WaBook(Go语言实现的MD电子书构建工具): <a href="https://github.com/wa-lang/wabook">https://github.com/wa-lang/wabook</a></em></li></ul><hr>
<h2>12.9. 几点忠告</h2>
<p>虽然反射提供的API远多于我们讲到的我们前面的例子主要是给出了一个方向通过反射可以实现哪些功能。反射是一个强大并富有表达力的工具但是它应该被小心地使用原因有三。</p>
<p>第一个原因是基于反射的代码是比较脆弱的。对于每一个会导致编译器报告类型错误的问题在反射中都有与之相对应的误用问题不同的是编译器会在构建时马上报告错误而反射则是在真正运行到的时候才会抛出panic异常可能是写完代码很久之后了而且程序也可能运行了很长的时间。</p>
<p>以前面的readList函数§12.6为例为了从输入读取字符串并填充int类型的变量而调用的reflect.Value.SetString方法可能导致panic异常。绝大多数使用反射的程序都有类似的风险需要非常小心地检查每个reflect.Value的对应值的类型、是否可取地址还有是否可以被修改等。</p>
<p>避免这种因反射而导致的脆弱性的问题的最好方法是将所有的反射相关的使用控制在包的内部如果可能的话避免在包的API中直接暴露reflect.Value类型这样可以限制一些非法输入。如果无法做到这一点在每个有风险的操作前指向额外的类型检查。以标准库中的代码为例当fmt.Printf收到一个非法的操作数时它并不会抛出panic异常而是打印相关的错误信息。程序虽然还有BUG但是会更加容易诊断。</p>
<pre><code class="language-Go">fmt.Printf(&quot;%d %s\n&quot;, &quot;hello&quot;, 42) // &quot;%!d(string=hello) %!s(int=42)&quot;
</code></pre>
<p>反射同样降低了程序的安全性,还影响了自动化重构和分析工具的准确性,因为它们无法识别运行时才能确认的类型信息。</p>
<p>避免使用反射的第二个原因是即使对应类型提供了相同文档但是反射的操作不能做静态类型检查而且大量反射的代码通常难以理解。总是需要小心翼翼地为每个导出的类型和其它接受interface{}或reflect.Value类型参数的函数维护说明文档。</p>
<p>第三个原因,基于反射的代码通常比正常的代码运行速度慢一到两个数量级。对于一个典型的项目,大部分函数的性能和程序的整体性能关系不大,所以当反射能使程序更加清晰的时候可以考虑使用。测试是一个特别适合使用反射的场景,因为每个测试的数据集都很小。但是对于性能关键路径的函数,最好避免使用反射。</p>
<hr><table><tr><td><img width="222px" src="https://chai2010.cn/advanced-go-programming-book/css.png"></td><td><img width="222px" src="https://chai2010.cn/advanced-go-programming-book/cch.png"></td></tr></table>
<div id="giscus-container"></div>
<footer class="page-footer">
<span>© 2015-2016 | <a href="https://github.com/gopl-zh"> Go语言圣经中文版</a>, 仅学习交流使用</span>
</footer>
</main>
<nav class="nav-wrapper" aria-label="Page navigation">
<!-- Mobile navigation buttons -->
<a rel="prev" href="../ch12/ch12-08.html" class="mobile-nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<!-- ../ch13/ch13.html -->
<a rel="next" href="../ch13/ch13.html" class="mobile-nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
<div style="clear: both"></div>
</nav>
</div>
</div>
<nav class="nav-wide-wrapper" aria-label="Page navigation">
<a rel="prev" href="../ch12/ch12-08.html" class="nav-chapters previous" title="Previous chapter" aria-label="Previous chapter" aria-keyshortcuts="Left">
<i class="fa fa-angle-left"></i>
</a>
<a rel="next" href="../ch13/ch13.html" class="nav-chapters next" title="Next chapter" aria-label="Next chapter" aria-keyshortcuts="Right">
<i class="fa fa-angle-right"></i>
</a>
</nav>
</div>
<script type="text/javascript">
window.playground_copyable = true;
</script>
<script src="../static/wabook/mark.min.js" type="text/javascript" charset="utf-8"></script>
<script src="../static/wabook/clipboard.min.js" type="text/javascript" charset="utf-8"></script>
<script src="../static/wabook/highlight.js" type="text/javascript" charset="utf-8"></script>
<script src="../static/wabook/book.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript" charset="utf-8">
var pagePath = "ch12/ch12-09.md"
</script>
<!-- Custom JS scripts -->
<script src="../static/wabook/giscus.js" type="text/javascript" charset="utf-8"></script>
</body>
</html>