mirror of
https://github.com/gopl-zh/gopl-zh.github.com.git
synced 2024-12-27 23:36:20 +00:00
2313 lines
100 KiB
HTML
2313 lines
100 KiB
HTML
<!DOCTYPE HTML>
|
|
<html lang="zh-tw" >
|
|
|
|
<head>
|
|
|
|
<meta charset="UTF-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
|
<title>Slice | Go语言圣经</title>
|
|
<meta content="text/html; charset=utf-8" http-equiv="Content-Type">
|
|
<meta name="description" content="">
|
|
<meta name="generator" content="GitBook 2.5.2">
|
|
|
|
|
|
<meta name="HandheldFriendly" content="true"/>
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
|
<meta name="apple-mobile-web-app-capable" content="yes">
|
|
<meta name="apple-mobile-web-app-status-bar-style" content="black">
|
|
<link rel="apple-touch-icon-precomposed" sizes="152x152" href="../gitbook/images/apple-touch-icon-precomposed-152.png">
|
|
<link rel="shortcut icon" href="../gitbook/images/favicon.ico" type="image/x-icon">
|
|
|
|
<link rel="stylesheet" href="../gitbook/style.css">
|
|
|
|
|
|
<link rel="stylesheet" href="../gitbook/plugins/gitbook-plugin-katex/katex.min.css">
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="../gitbook/plugins/gitbook-plugin-highlight/website.css">
|
|
|
|
|
|
|
|
<link rel="stylesheet" href="../gitbook/plugins/gitbook-plugin-fontsettings/website.css">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<link rel="next" href="../ch4/ch4-03.html" />
|
|
|
|
|
|
<link rel="prev" href="../ch4/ch4-01.html" />
|
|
|
|
|
|
|
|
</head>
|
|
<body>
|
|
|
|
|
|
<div class="book" data-level="4.2" data-chapter-title="Slice" data-filepath="ch4/ch4-02.md" data-basepath=".." data-revision="Thu Dec 31 2015 16:18:40 GMT+0800 (中国标准时间)">
|
|
|
|
|
|
<div class="book-summary">
|
|
<nav role="navigation">
|
|
<ul class="summary">
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
<li class="chapter " data-level="0" data-path="index.html">
|
|
|
|
|
|
<a href="../index.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
前言
|
|
</a>
|
|
|
|
|
|
<ul class="articles">
|
|
|
|
|
|
<li class="chapter " data-level="0.1" data-path="ch0/ch0-01.html">
|
|
|
|
|
|
<a href="../ch0/ch0-01.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>0.1.</b>
|
|
|
|
Go語言起源
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="0.2" data-path="ch0/ch0-02.html">
|
|
|
|
|
|
<a href="../ch0/ch0-02.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>0.2.</b>
|
|
|
|
Go語言項目
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="0.3" data-path="ch0/ch0-03.html">
|
|
|
|
|
|
<a href="../ch0/ch0-03.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>0.3.</b>
|
|
|
|
本書的組織
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="0.4" data-path="ch0/ch0-04.html">
|
|
|
|
|
|
<a href="../ch0/ch0-04.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>0.4.</b>
|
|
|
|
更多的信息
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="0.5" data-path="ch0/ch0-05.html">
|
|
|
|
|
|
<a href="../ch0/ch0-05.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>0.5.</b>
|
|
|
|
致謝
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="1" data-path="ch1/ch1.html">
|
|
|
|
|
|
<a href="../ch1/ch1.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>1.</b>
|
|
|
|
入門
|
|
</a>
|
|
|
|
|
|
<ul class="articles">
|
|
|
|
|
|
<li class="chapter " data-level="1.1" data-path="ch1/ch1-01.html">
|
|
|
|
|
|
<a href="../ch1/ch1-01.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>1.1.</b>
|
|
|
|
Hello, World
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="1.2" data-path="ch1/ch1-02.html">
|
|
|
|
|
|
<a href="../ch1/ch1-02.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>1.2.</b>
|
|
|
|
命令行參數
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="1.3" data-path="ch1/ch1-03.html">
|
|
|
|
|
|
<a href="../ch1/ch1-03.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>1.3.</b>
|
|
|
|
査找重複的行
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="1.4" data-path="ch1/ch1-04.html">
|
|
|
|
|
|
<a href="../ch1/ch1-04.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>1.4.</b>
|
|
|
|
GIF動畵
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="1.5" data-path="ch1/ch1-05.html">
|
|
|
|
|
|
<a href="../ch1/ch1-05.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>1.5.</b>
|
|
|
|
獲取URL
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="1.6" data-path="ch1/ch1-06.html">
|
|
|
|
|
|
<a href="../ch1/ch1-06.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>1.6.</b>
|
|
|
|
併發獲取多個URL
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="1.7" data-path="ch1/ch1-07.html">
|
|
|
|
|
|
<a href="../ch1/ch1-07.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>1.7.</b>
|
|
|
|
Web服務
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="1.8" data-path="ch1/ch1-08.html">
|
|
|
|
|
|
<a href="../ch1/ch1-08.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>1.8.</b>
|
|
|
|
本章要點
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="2" data-path="ch2/ch2.html">
|
|
|
|
|
|
<a href="../ch2/ch2.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>2.</b>
|
|
|
|
程序結構
|
|
</a>
|
|
|
|
|
|
<ul class="articles">
|
|
|
|
|
|
<li class="chapter " data-level="2.1" data-path="ch2/ch2-01.html">
|
|
|
|
|
|
<a href="../ch2/ch2-01.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>2.1.</b>
|
|
|
|
命名
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="2.2" data-path="ch2/ch2-02.html">
|
|
|
|
|
|
<a href="../ch2/ch2-02.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>2.2.</b>
|
|
|
|
聲明
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="2.3" data-path="ch2/ch2-03.html">
|
|
|
|
|
|
<a href="../ch2/ch2-03.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>2.3.</b>
|
|
|
|
變量
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="2.4" data-path="ch2/ch2-04.html">
|
|
|
|
|
|
<a href="../ch2/ch2-04.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>2.4.</b>
|
|
|
|
賦值
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="2.5" data-path="ch2/ch2-05.html">
|
|
|
|
|
|
<a href="../ch2/ch2-05.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>2.5.</b>
|
|
|
|
類型
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="2.6" data-path="ch2/ch2-06.html">
|
|
|
|
|
|
<a href="../ch2/ch2-06.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>2.6.</b>
|
|
|
|
包和文件
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="2.7" data-path="ch2/ch2-07.html">
|
|
|
|
|
|
<a href="../ch2/ch2-07.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>2.7.</b>
|
|
|
|
作用域
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="3" data-path="ch3/ch3.html">
|
|
|
|
|
|
<a href="../ch3/ch3.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>3.</b>
|
|
|
|
基礎數據類型
|
|
</a>
|
|
|
|
|
|
<ul class="articles">
|
|
|
|
|
|
<li class="chapter " data-level="3.1" data-path="ch3/ch3-01.html">
|
|
|
|
|
|
<a href="../ch3/ch3-01.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>3.1.</b>
|
|
|
|
整型
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="3.2" data-path="ch3/ch3-02.html">
|
|
|
|
|
|
<a href="../ch3/ch3-02.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>3.2.</b>
|
|
|
|
浮點數
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="3.3" data-path="ch3/ch3-03.html">
|
|
|
|
|
|
<a href="../ch3/ch3-03.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>3.3.</b>
|
|
|
|
複數
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="3.4" data-path="ch3/ch3-04.html">
|
|
|
|
|
|
<a href="../ch3/ch3-04.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>3.4.</b>
|
|
|
|
布爾型
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="3.5" data-path="ch3/ch3-05.html">
|
|
|
|
|
|
<a href="../ch3/ch3-05.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>3.5.</b>
|
|
|
|
字符串
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="3.6" data-path="ch3/ch3-06.html">
|
|
|
|
|
|
<a href="../ch3/ch3-06.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>3.6.</b>
|
|
|
|
常量
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="4" data-path="ch4/ch4.html">
|
|
|
|
|
|
<a href="../ch4/ch4.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>4.</b>
|
|
|
|
複合數據類型
|
|
</a>
|
|
|
|
|
|
<ul class="articles">
|
|
|
|
|
|
<li class="chapter " data-level="4.1" data-path="ch4/ch4-01.html">
|
|
|
|
|
|
<a href="../ch4/ch4-01.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>4.1.</b>
|
|
|
|
數組
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter active" data-level="4.2" data-path="ch4/ch4-02.html">
|
|
|
|
|
|
<a href="../ch4/ch4-02.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>4.2.</b>
|
|
|
|
Slice
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="4.3" data-path="ch4/ch4-03.html">
|
|
|
|
|
|
<a href="../ch4/ch4-03.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>4.3.</b>
|
|
|
|
Map
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="4.4" data-path="ch4/ch4-04.html">
|
|
|
|
|
|
<a href="../ch4/ch4-04.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>4.4.</b>
|
|
|
|
結構體
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="4.5" data-path="ch4/ch4-05.html">
|
|
|
|
|
|
<a href="../ch4/ch4-05.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>4.5.</b>
|
|
|
|
JSON
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="4.6" data-path="ch4/ch4-06.html">
|
|
|
|
|
|
<a href="../ch4/ch4-06.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>4.6.</b>
|
|
|
|
文本和HTML模闆
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="5" data-path="ch5/ch5.html">
|
|
|
|
|
|
<a href="../ch5/ch5.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>5.</b>
|
|
|
|
函數
|
|
</a>
|
|
|
|
|
|
<ul class="articles">
|
|
|
|
|
|
<li class="chapter " data-level="5.1" data-path="ch5/ch5-01.html">
|
|
|
|
|
|
<a href="../ch5/ch5-01.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>5.1.</b>
|
|
|
|
函數聲明
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="5.2" data-path="ch5/ch5-02.html">
|
|
|
|
|
|
<a href="../ch5/ch5-02.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>5.2.</b>
|
|
|
|
遞歸
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="5.3" data-path="ch5/ch5-03.html">
|
|
|
|
|
|
<a href="../ch5/ch5-03.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>5.3.</b>
|
|
|
|
多返迴值
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="5.4" data-path="ch5/ch5-04.html">
|
|
|
|
|
|
<a href="../ch5/ch5-04.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>5.4.</b>
|
|
|
|
錯誤
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="5.5" data-path="ch5/ch5-05.html">
|
|
|
|
|
|
<a href="../ch5/ch5-05.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>5.5.</b>
|
|
|
|
函數值
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="5.6" data-path="ch5/ch5-06.html">
|
|
|
|
|
|
<a href="../ch5/ch5-06.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>5.6.</b>
|
|
|
|
匿名函數
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="5.7" data-path="ch5/ch5-07.html">
|
|
|
|
|
|
<a href="../ch5/ch5-07.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>5.7.</b>
|
|
|
|
可變參數
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="5.8" data-path="ch5/ch5-08.html">
|
|
|
|
|
|
<a href="../ch5/ch5-08.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>5.8.</b>
|
|
|
|
Deferred函數
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="5.9" data-path="ch5/ch5-09.html">
|
|
|
|
|
|
<a href="../ch5/ch5-09.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>5.9.</b>
|
|
|
|
Panic異常
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="5.10" data-path="ch5/ch5-10.html">
|
|
|
|
|
|
<a href="../ch5/ch5-10.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>5.10.</b>
|
|
|
|
Recover捕獲異常
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="6" data-path="ch6/ch6.html">
|
|
|
|
|
|
<a href="../ch6/ch6.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>6.</b>
|
|
|
|
方法
|
|
</a>
|
|
|
|
|
|
<ul class="articles">
|
|
|
|
|
|
<li class="chapter " data-level="6.1" data-path="ch6/ch6-01.html">
|
|
|
|
|
|
<a href="../ch6/ch6-01.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>6.1.</b>
|
|
|
|
方法聲明
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="6.2" data-path="ch6/ch6-02.html">
|
|
|
|
|
|
<a href="../ch6/ch6-02.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>6.2.</b>
|
|
|
|
基於指針對象的方法
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="6.3" data-path="ch6/ch6-03.html">
|
|
|
|
|
|
<a href="../ch6/ch6-03.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>6.3.</b>
|
|
|
|
通過嵌入結構體來擴展類型
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="6.4" data-path="ch6/ch6-04.html">
|
|
|
|
|
|
<a href="../ch6/ch6-04.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>6.4.</b>
|
|
|
|
方法值和方法表達式
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="6.5" data-path="ch6/ch6-05.html">
|
|
|
|
|
|
<a href="../ch6/ch6-05.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>6.5.</b>
|
|
|
|
示例: Bit數組
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="6.6" data-path="ch6/ch6-06.html">
|
|
|
|
|
|
<a href="../ch6/ch6-06.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>6.6.</b>
|
|
|
|
封裝
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="7" data-path="ch7/ch7.html">
|
|
|
|
|
|
<a href="../ch7/ch7.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>7.</b>
|
|
|
|
接口
|
|
</a>
|
|
|
|
|
|
<ul class="articles">
|
|
|
|
|
|
<li class="chapter " data-level="7.1" data-path="ch7/ch7-01.html">
|
|
|
|
|
|
<a href="../ch7/ch7-01.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>7.1.</b>
|
|
|
|
接口是合約
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="7.2" data-path="ch7/ch7-02.html">
|
|
|
|
|
|
<a href="../ch7/ch7-02.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>7.2.</b>
|
|
|
|
接口類型
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="7.3" data-path="ch7/ch7-03.html">
|
|
|
|
|
|
<a href="../ch7/ch7-03.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>7.3.</b>
|
|
|
|
實現接口的條件
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="7.4" data-path="ch7/ch7-04.html">
|
|
|
|
|
|
<a href="../ch7/ch7-04.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>7.4.</b>
|
|
|
|
flag.Value接口
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="7.5" data-path="ch7/ch7-05.html">
|
|
|
|
|
|
<a href="../ch7/ch7-05.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>7.5.</b>
|
|
|
|
接口值
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="7.6" data-path="ch7/ch7-06.html">
|
|
|
|
|
|
<a href="../ch7/ch7-06.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>7.6.</b>
|
|
|
|
sort.Interface接口
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="7.7" data-path="ch7/ch7-07.html">
|
|
|
|
|
|
<a href="../ch7/ch7-07.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>7.7.</b>
|
|
|
|
http.Handler接口
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="7.8" data-path="ch7/ch7-08.html">
|
|
|
|
|
|
<a href="../ch7/ch7-08.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>7.8.</b>
|
|
|
|
error接口
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="7.9" data-path="ch7/ch7-09.html">
|
|
|
|
|
|
<a href="../ch7/ch7-09.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>7.9.</b>
|
|
|
|
示例: 表達式求值
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="7.10" data-path="ch7/ch7-10.html">
|
|
|
|
|
|
<a href="../ch7/ch7-10.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>7.10.</b>
|
|
|
|
類型斷言
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="7.11" data-path="ch7/ch7-11.html">
|
|
|
|
|
|
<a href="../ch7/ch7-11.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>7.11.</b>
|
|
|
|
基於類型斷言識别錯誤類型
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="7.12" data-path="ch7/ch7-12.html">
|
|
|
|
|
|
<a href="../ch7/ch7-12.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>7.12.</b>
|
|
|
|
通過類型斷言査詢接口
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="7.13" data-path="ch7/ch7-13.html">
|
|
|
|
|
|
<a href="../ch7/ch7-13.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>7.13.</b>
|
|
|
|
類型分支
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="7.14" data-path="ch7/ch7-14.html">
|
|
|
|
|
|
<a href="../ch7/ch7-14.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>7.14.</b>
|
|
|
|
示例: 基於標記的XML解碼
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="7.15" data-path="ch7/ch7-15.html">
|
|
|
|
|
|
<a href="../ch7/ch7-15.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>7.15.</b>
|
|
|
|
補充幾點
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="8" data-path="ch8/ch8.html">
|
|
|
|
|
|
<a href="../ch8/ch8.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>8.</b>
|
|
|
|
Goroutines和Channels
|
|
</a>
|
|
|
|
|
|
<ul class="articles">
|
|
|
|
|
|
<li class="chapter " data-level="8.1" data-path="ch8/ch8-01.html">
|
|
|
|
|
|
<a href="../ch8/ch8-01.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>8.1.</b>
|
|
|
|
Goroutines
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="8.2" data-path="ch8/ch8-02.html">
|
|
|
|
|
|
<a href="../ch8/ch8-02.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>8.2.</b>
|
|
|
|
示例: 併發的Clock服務
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="8.3" data-path="ch8/ch8-03.html">
|
|
|
|
|
|
<a href="../ch8/ch8-03.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>8.3.</b>
|
|
|
|
示例: 併發的Echo服務
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="8.4" data-path="ch8/ch8-04.html">
|
|
|
|
|
|
<a href="../ch8/ch8-04.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>8.4.</b>
|
|
|
|
Channels
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="8.5" data-path="ch8/ch8-05.html">
|
|
|
|
|
|
<a href="../ch8/ch8-05.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>8.5.</b>
|
|
|
|
併行的循環
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="8.6" data-path="ch8/ch8-06.html">
|
|
|
|
|
|
<a href="../ch8/ch8-06.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>8.6.</b>
|
|
|
|
示例: 併發的Web爬蟲
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="8.7" data-path="ch8/ch8-07.html">
|
|
|
|
|
|
<a href="../ch8/ch8-07.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>8.7.</b>
|
|
|
|
基於select的多路複用
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="8.8" data-path="ch8/ch8-08.html">
|
|
|
|
|
|
<a href="../ch8/ch8-08.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>8.8.</b>
|
|
|
|
示例: 併發的字典遍歷
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="8.9" data-path="ch8/ch8-09.html">
|
|
|
|
|
|
<a href="../ch8/ch8-09.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>8.9.</b>
|
|
|
|
併發的退出
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="8.10" data-path="ch8/ch8-10.html">
|
|
|
|
|
|
<a href="../ch8/ch8-10.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>8.10.</b>
|
|
|
|
示例: 聊天服務
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="9" data-path="ch9/ch9.html">
|
|
|
|
|
|
<a href="../ch9/ch9.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>9.</b>
|
|
|
|
基於共享變量的併發
|
|
</a>
|
|
|
|
|
|
<ul class="articles">
|
|
|
|
|
|
<li class="chapter " data-level="9.1" data-path="ch9/ch9-01.html">
|
|
|
|
|
|
<a href="../ch9/ch9-01.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>9.1.</b>
|
|
|
|
競爭條件
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="9.2" data-path="ch9/ch9-02.html">
|
|
|
|
|
|
<a href="../ch9/ch9-02.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>9.2.</b>
|
|
|
|
sync.Mutex互斥鎖
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="9.3" data-path="ch9/ch9-03.html">
|
|
|
|
|
|
<a href="../ch9/ch9-03.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>9.3.</b>
|
|
|
|
sync.RWMutex讀寫鎖
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="9.4" data-path="ch9/ch9-04.html">
|
|
|
|
|
|
<a href="../ch9/ch9-04.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>9.4.</b>
|
|
|
|
內存同步
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="9.5" data-path="ch9/ch9-05.html">
|
|
|
|
|
|
<a href="../ch9/ch9-05.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>9.5.</b>
|
|
|
|
sync.Once初始化
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="9.6" data-path="ch9/ch9-06.html">
|
|
|
|
|
|
<a href="../ch9/ch9-06.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>9.6.</b>
|
|
|
|
競爭條件檢測
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="9.7" data-path="ch9/ch9-07.html">
|
|
|
|
|
|
<a href="../ch9/ch9-07.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>9.7.</b>
|
|
|
|
示例: 併發的非阻塞緩存
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="9.8" data-path="ch9/ch9-08.html">
|
|
|
|
|
|
<a href="../ch9/ch9-08.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>9.8.</b>
|
|
|
|
Goroutines和線程
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="10" data-path="ch10/ch10.html">
|
|
|
|
|
|
<a href="../ch10/ch10.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>10.</b>
|
|
|
|
包和工具
|
|
</a>
|
|
|
|
|
|
<ul class="articles">
|
|
|
|
|
|
<li class="chapter " data-level="10.1" data-path="ch10/ch10-01.html">
|
|
|
|
|
|
<a href="../ch10/ch10-01.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>10.1.</b>
|
|
|
|
簡介
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="10.2" data-path="ch10/ch10-02.html">
|
|
|
|
|
|
<a href="../ch10/ch10-02.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>10.2.</b>
|
|
|
|
導入路徑
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="10.3" data-path="ch10/ch10-03.html">
|
|
|
|
|
|
<a href="../ch10/ch10-03.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>10.3.</b>
|
|
|
|
包聲明
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="10.4" data-path="ch10/ch10-04.html">
|
|
|
|
|
|
<a href="../ch10/ch10-04.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>10.4.</b>
|
|
|
|
導入聲明
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="10.5" data-path="ch10/ch10-05.html">
|
|
|
|
|
|
<a href="../ch10/ch10-05.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>10.5.</b>
|
|
|
|
匿名導入
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="10.6" data-path="ch10/ch10-06.html">
|
|
|
|
|
|
<a href="../ch10/ch10-06.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>10.6.</b>
|
|
|
|
包和命名
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="10.7" data-path="ch10/ch10-07.html">
|
|
|
|
|
|
<a href="../ch10/ch10-07.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>10.7.</b>
|
|
|
|
工具
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="11" data-path="ch11/ch11.html">
|
|
|
|
|
|
<a href="../ch11/ch11.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>11.</b>
|
|
|
|
測試
|
|
</a>
|
|
|
|
|
|
<ul class="articles">
|
|
|
|
|
|
<li class="chapter " data-level="11.1" data-path="ch11/ch11-01.html">
|
|
|
|
|
|
<a href="../ch11/ch11-01.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>11.1.</b>
|
|
|
|
go test
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="11.2" data-path="ch11/ch11-02.html">
|
|
|
|
|
|
<a href="../ch11/ch11-02.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>11.2.</b>
|
|
|
|
測試函數
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="11.3" data-path="ch11/ch11-03.html">
|
|
|
|
|
|
<a href="../ch11/ch11-03.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>11.3.</b>
|
|
|
|
測試覆蓋率
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="11.4" data-path="ch11/ch11-04.html">
|
|
|
|
|
|
<a href="../ch11/ch11-04.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>11.4.</b>
|
|
|
|
基準測試
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="11.5" data-path="ch11/ch11-05.html">
|
|
|
|
|
|
<a href="../ch11/ch11-05.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>11.5.</b>
|
|
|
|
剖析
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="11.6" data-path="ch11/ch11-06.html">
|
|
|
|
|
|
<a href="../ch11/ch11-06.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>11.6.</b>
|
|
|
|
示例函數
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="12" data-path="ch12/ch12.html">
|
|
|
|
|
|
<a href="../ch12/ch12.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>12.</b>
|
|
|
|
反射
|
|
</a>
|
|
|
|
|
|
<ul class="articles">
|
|
|
|
|
|
<li class="chapter " data-level="12.1" data-path="ch12/ch12-01.html">
|
|
|
|
|
|
<a href="../ch12/ch12-01.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>12.1.</b>
|
|
|
|
爲何需要反射?
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="12.2" data-path="ch12/ch12-02.html">
|
|
|
|
|
|
<a href="../ch12/ch12-02.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>12.2.</b>
|
|
|
|
reflect.Type和reflect.Value
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="12.3" data-path="ch12/ch12-03.html">
|
|
|
|
|
|
<a href="../ch12/ch12-03.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>12.3.</b>
|
|
|
|
Display遞歸打印
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="12.4" data-path="ch12/ch12-04.html">
|
|
|
|
|
|
<a href="../ch12/ch12-04.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>12.4.</b>
|
|
|
|
示例: 編碼S表達式
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="12.5" data-path="ch12/ch12-05.html">
|
|
|
|
|
|
<a href="../ch12/ch12-05.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>12.5.</b>
|
|
|
|
通過reflect.Value脩改值
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="12.6" data-path="ch12/ch12-06.html">
|
|
|
|
|
|
<a href="../ch12/ch12-06.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>12.6.</b>
|
|
|
|
示例: 解碼S表達式
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="12.7" data-path="ch12/ch12-07.html">
|
|
|
|
|
|
<a href="../ch12/ch12-07.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>12.7.</b>
|
|
|
|
獲取結構體字段標識
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="12.8" data-path="ch12/ch12-08.html">
|
|
|
|
|
|
<a href="../ch12/ch12-08.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>12.8.</b>
|
|
|
|
顯示一個類型的方法集
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="12.9" data-path="ch12/ch12-09.html">
|
|
|
|
|
|
<a href="../ch12/ch12-09.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>12.9.</b>
|
|
|
|
幾點忠告
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="13" data-path="ch13/ch13.html">
|
|
|
|
|
|
<a href="../ch13/ch13.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>13.</b>
|
|
|
|
底層編程
|
|
</a>
|
|
|
|
|
|
<ul class="articles">
|
|
|
|
|
|
<li class="chapter " data-level="13.1" data-path="ch13/ch13-01.html">
|
|
|
|
|
|
<a href="../ch13/ch13-01.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>13.1.</b>
|
|
|
|
unsafe.Sizeof, Alignof 和 Offsetof
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="13.2" data-path="ch13/ch13-02.html">
|
|
|
|
|
|
<a href="../ch13/ch13-02.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>13.2.</b>
|
|
|
|
unsafe.Pointer
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="13.3" data-path="ch13/ch13-03.html">
|
|
|
|
|
|
<a href="../ch13/ch13-03.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>13.3.</b>
|
|
|
|
示例: 深度相等判斷
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="13.4" data-path="ch13/ch13-04.html">
|
|
|
|
|
|
<a href="../ch13/ch13-04.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>13.4.</b>
|
|
|
|
通過cgo調用C代碼
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="13.5" data-path="ch13/ch13-05.html">
|
|
|
|
|
|
<a href="../ch13/ch13-05.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>13.5.</b>
|
|
|
|
幾點忠告
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
</ul>
|
|
|
|
</li>
|
|
|
|
<li class="chapter " data-level="14" data-path="CONTRIBUTORS.html">
|
|
|
|
|
|
<a href="../CONTRIBUTORS.html">
|
|
|
|
<i class="fa fa-check"></i>
|
|
|
|
<b>14.</b>
|
|
|
|
附録
|
|
</a>
|
|
|
|
|
|
</li>
|
|
|
|
|
|
|
|
|
|
<li class="divider"></li>
|
|
<li>
|
|
<a href="https://www.gitbook.com" target="blank" class="gitbook-link">
|
|
本書使用 GitBook 釋出
|
|
</a>
|
|
</li>
|
|
|
|
</ul>
|
|
</nav>
|
|
</div>
|
|
|
|
<div class="book-body">
|
|
<div class="body-inner">
|
|
<div class="book-header" role="navigation">
|
|
<!-- Actions Left -->
|
|
|
|
|
|
<!-- Title -->
|
|
<h1>
|
|
<i class="fa fa-circle-o-notch fa-spin"></i>
|
|
<a href="../" >Go语言圣经</a>
|
|
</h1>
|
|
</div>
|
|
|
|
<div class="page-wrapper" tabindex="-1" role="main">
|
|
<div class="page-inner">
|
|
|
|
|
|
<section class="normal" id="section-">
|
|
|
|
<h2 id="42-slice">4.2. Slice</h2>
|
|
<p>Slice(切片)代表變長的序列,序列中每個元素都有相同的類型。一個slice類型一般寫作[]T,其中T代表slice中元素的類型;語法和數組很像隻是沒有長度而已。</p>
|
|
<p>數組和slice之間有着緊密的聯繫。一個slice是一個輕量級的數據結果,提供了訪問數組子序列(或者全部)元素的功能,因爲slice的底層確實引用一個數組對象。一個slice有三個部分構成:指針、長度和容量。指針指向第一個元素對應的底層數組元素的地址,slice的第一個元素併不一定就是數組的第一個元素。長度對應slice中元素的數目;長度不能超過容量,容量一般是從slice的開始位置到底層數據的結尾位置。內置的len和cap函數分别返迴slice的長度和容量。</p>
|
|
<p>多個slice之間可以共享底層的數據,併且引用的數組部分區間可能重疊。圖4.1顯示了表示一年中每個月份名字的字符串數組,還有重疊引用了該數組的兩個slice。數組這樣定義</p>
|
|
<pre><code class="lang-Go">months := [...]<span class="hljs-typename">string</span>{<span class="hljs-number">1</span>: <span class="hljs-string">"January"</span>, <span class="hljs-comment">/* ... */</span>, <span class="hljs-number">12</span>: <span class="hljs-string">"December"</span>}
|
|
</code></pre>
|
|
<p>因此一月份是months[1],十二月份是months[12]。通常,數組的第一個元素從索引0開始,但是月份一般是從1開始的,因此我們聲明數組時直接第0個元素,第0個元素會被自動初始化爲空字符串。</p>
|
|
<p>slice的操作s[i:j],其中0 ≤ i≤ j≤ cap(s),用於創建一個新的slice,引用s的從第i個元素開始到第j-1個元素的子序列。新的slice將隻有j-i個元素。如果i位置的索引被省略的話將使用0代替,如果j位置的索引被省略的話將使用len(s)代替。因此,months[1:13]切片操作將引用全部有效的月份,和months[1:]操作等價;months[:]切片操作則是引用整個數組。讓我們分别定義表示第二季度和北方夏天的slice,它們有重疊部分:</p>
|
|
<p><img src="../images/ch4-01.png" alt=""></p>
|
|
<pre><code class="lang-Go">Q2 := months[<span class="hljs-number">4</span>:<span class="hljs-number">7</span>]
|
|
summer := months[<span class="hljs-number">6</span>:<span class="hljs-number">9</span>]
|
|
fmt.Println(Q2) <span class="hljs-comment">// ["April" "May" "June"]</span>
|
|
fmt.Println(summer) <span class="hljs-comment">// ["June" "July" "August"]</span>
|
|
</code></pre>
|
|
<p>兩個slice都包含了六月份,下面的代碼是一個包含相同月份的測試(性能較低):</p>
|
|
<pre><code class="lang-Go"><span class="hljs-keyword">for</span> _, s := <span class="hljs-keyword">range</span> summer {
|
|
<span class="hljs-keyword">for</span> _, q := <span class="hljs-keyword">range</span> Q2 {
|
|
<span class="hljs-keyword">if</span> s == q {
|
|
fmt.Printf(<span class="hljs-string">"%s appears in both\n"</span>, s)
|
|
}
|
|
}
|
|
}
|
|
</code></pre>
|
|
<p>如果切片操作長處cap(s)的上限將導致一個panic異常,但是超出len(s)則是擴展了slice,因此新slice的長度會變大:</p>
|
|
<pre><code class="lang-Go">fmt.Println(summer[:<span class="hljs-number">20</span>]) <span class="hljs-comment">// panic: out of range</span>
|
|
|
|
endlessSummer := summer[:<span class="hljs-number">5</span>] <span class="hljs-comment">// extend a slice (within capacity)</span>
|
|
fmt.Println(endlessSummer) <span class="hljs-comment">// "[June July August September October]"</span>
|
|
</code></pre>
|
|
<p>另外,字符串的切片操作和[]byte字節類型切片的切片操作是類似的。它們都寫作x[m:n],併且都是返迴一個原始字節繫列的子序列,底層都是共享之前的底層數組,因此切片操作對應常量時間複雜度。x[m:n]切片操作對於字符串則生成一個新字符串,如果x是[]byte的話則生成一個新的[]byte。</p>
|
|
<p>因爲slice值包含指向第一個元素的指針,因此向函數傳遞slice將運行在函數內部脩改底層數組的元素。換句話説,複雜一個slice隻是對底層的數組創建了一個新的slice别名(§2.3.2)。下面的reverse函數在原內存空間將[]int類型的slice反轉,而且它可以用於任意長度的slice。</p>
|
|
<pre><code class="lang-Go">gopl.io/ch4/rev
|
|
|
|
<span class="hljs-comment">// reverse reverses a slice of ints in place.</span>
|
|
<span class="hljs-keyword">func</span> reverse(s []<span class="hljs-typename">int</span>) {
|
|
<span class="hljs-keyword">for</span> i, j := <span class="hljs-number">0</span>, <span class="hljs-built_in">len</span>(s)-<span class="hljs-number">1</span>; i < j; i, j = i+<span class="hljs-number">1</span>, j-<span class="hljs-number">1</span> {
|
|
s[i], s[j] = s[j], s[i]
|
|
}
|
|
}
|
|
</code></pre>
|
|
<p>這里我們反轉數組的應用:</p>
|
|
<pre><code class="lang-Go">a := [...]<span class="hljs-typename">int</span>{<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>}
|
|
reverse(a[:])
|
|
fmt.Println(a) <span class="hljs-comment">// "[5 4 3 2 1 0]"</span>
|
|
</code></pre>
|
|
<p>一種將slice元素循環向左镟轉n個元素的方法是三次調用reverse反轉函數,第一次是反轉開頭的n個元素,然後是反轉剩下的元素,最後是反轉整個slice的元素。(如果是向右循環镟轉,則將第三個函數調用移到第一個調用位置就可以了。)</p>
|
|
<pre><code class="lang-Go">s := []<span class="hljs-typename">int</span>{<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>}
|
|
<span class="hljs-comment">// Rotate s left by two positions.</span>
|
|
reverse(s[:<span class="hljs-number">2</span>])
|
|
reverse(s[<span class="hljs-number">2</span>:])
|
|
reverse(s)
|
|
fmt.Println(s) <span class="hljs-comment">// "[2 3 4 5 0 1]"</span>
|
|
</code></pre>
|
|
<p>要註意的是slice類型的變量s和數組類型的變量a的初始化語法的差異。slice和數組的字面值語法很類似,它們都是用花括弧包含一繫列的初始化元素,但是對於slice併沒有指明序列的長度。這會隱式地創建一個合適大小的數組,然後slice的指針指向底層的數組。就像數組字面值一樣,slice的字面值也可以按順序指定初始化值序列,或者是通過索引和元素值指定,或者的兩種風格的混合語法初始化。</p>
|
|
<p>和數組不同的是,slice不能比較,因此我們不能使用==操作符來判斷兩個slice是否有相同的元素。不過標準庫提供了高度優化的bytes.Equal函數來判斷兩個字節型slice是否相等([]byte),但是對於其他類型的slice,我們必鬚自己展開每個元素進行比較:</p>
|
|
<pre><code class="lang-Go"><span class="hljs-keyword">func</span> equal(x, y []<span class="hljs-typename">string</span>) <span class="hljs-typename">bool</span> {
|
|
<span class="hljs-keyword">if</span> <span class="hljs-built_in">len</span>(x) != <span class="hljs-built_in">len</span>(y) {
|
|
<span class="hljs-keyword">return</span> <span class="hljs-constant">false</span>
|
|
}
|
|
<span class="hljs-keyword">for</span> i := <span class="hljs-keyword">range</span> x {
|
|
<span class="hljs-keyword">if</span> x[i] != y[i] {
|
|
<span class="hljs-keyword">return</span> <span class="hljs-constant">false</span>
|
|
}
|
|
}
|
|
<span class="hljs-keyword">return</span> <span class="hljs-constant">true</span>
|
|
}
|
|
</code></pre>
|
|
<p>上面關於兩個slice的深度相等測試,運行的時間併不比支持==操作的數組或字符串更多,但是爲何slice卻不支持比較運算符呢?這方面有兩個原因。第一個原因,一個slice的元素是間接引用的,一個slice甚至可以包含自身。雖然有很多辦法處理這種情形,但是沒有一個是簡單有效的。</p>
|
|
<p>第二個原因,因爲slice的元素是間接引用的,一個固定值的slice在不同的時間可能包含不同的元素,因爲底層數組的元素可能會被脩改。併且Go語言中map等哈希表之類的數據結構的key隻做簡單的淺拷貝,它要求在整個聲明週期中相等的key必鬚對相同的元素。對於像指針或chan之類的引用類型,==相等測試可以判斷兩個是否是引用相同的對象。一個針對slice的淺相等測試的==操作符可能是有一定用處的,也能臨時解決map類型的key問題,但是slice和數組不同的相等測試行爲會讓人睏惑。因此,安全的做飯是直接禁止slice之間的比較操作。</p>
|
|
<p>slice唯一合法的比較是和nil比較,例如:</p>
|
|
<pre><code class="lang-Go"><span class="hljs-keyword">if</span> summer == <span class="hljs-constant">nil</span> { <span class="hljs-comment">/* ... */</span> }
|
|
</code></pre>
|
|
<p>一個零值的slice等於nil。一個nil值的slice併沒有底層數組。一個nil值的slice的長度和容量都是0,但是也有非nil值的slice的長度和容量也是0的,例如[]int{}或make([]int, 3)[3:]。與任意類型的nil值一樣,我們可以用[]int(nil)類型轉換表達式來生成一個對應類型slice的nil值。</p>
|
|
<pre><code class="lang-Go"><span class="hljs-keyword">var</span> s []<span class="hljs-typename">int</span> <span class="hljs-comment">// len(s) == 0, s == nil</span>
|
|
s = <span class="hljs-constant">nil</span> <span class="hljs-comment">// len(s) == 0, s == nil</span>
|
|
s = []<span class="hljs-typename">int</span>(<span class="hljs-constant">nil</span>) <span class="hljs-comment">// len(s) == 0, s == nil</span>
|
|
s = []<span class="hljs-typename">int</span>{} <span class="hljs-comment">// len(s) == 0, s != nil</span>
|
|
</code></pre>
|
|
<p>如果你需要測試一個slice是否是空的,使用len(s) == 0來判斷,而不是用s == nil來判斷。除了和nil相等比較外,一個nil值的slice的行爲和其它任意0産長度的slice一樣;例如reverse(nil)也是安全的。除了文檔已經明確説明的地方,所有的Go語言函數應該以相同的方式對待nil值的slice和0長度的slice。</p>
|
|
<p>內置的make函數創建一個指定元素類型、長度和容量的slice。容量部分可以省略,在這種情況下,容量將等於長度。</p>
|
|
<pre><code class="lang-Go"><span class="hljs-built_in">make</span>([]T, <span class="hljs-built_in">len</span>)
|
|
<span class="hljs-built_in">make</span>([]T, <span class="hljs-built_in">len</span>, <span class="hljs-built_in">cap</span>) <span class="hljs-comment">// same as make([]T, cap)[:len]</span>
|
|
</code></pre>
|
|
<p>在底層,make創建了一個匿名的數組變量,然後返迴一個slice;隻有通過返迴的slice才能引用底層匿名的數組變量。在第一種語句中,slice是整個數組的view。在第二個語句中,slice隻引用了底層數組的前len個元素,但是容量將包含整個的數組。額外的元素是留給未來的增長用的。</p>
|
|
<h3 id="421-append函數">4.2.1. append函數</h3>
|
|
<p>內置的append函數用於向slice追加元素:</p>
|
|
<pre><code class="lang-Go"><span class="hljs-keyword">var</span> runes []<span class="hljs-typename">rune</span>
|
|
<span class="hljs-keyword">for</span> _, r := <span class="hljs-keyword">range</span> <span class="hljs-string">"Hello, 世界"</span> {
|
|
runes = <span class="hljs-built_in">append</span>(runes, r)
|
|
}
|
|
fmt.Printf(<span class="hljs-string">"%q\n"</span>, runes) <span class="hljs-comment">// "['H' 'e' 'l' 'l' 'o' ',' ' ' '世' '界']"</span>
|
|
</code></pre>
|
|
<p>在循環中使用append函數構建一個有九個rune字符構成的slice,當然對應這個特殊的問題我們可以通過Go語言內置的[]rune("Hello, 世界")轉換操作完成。</p>
|
|
<p>append函數對於理解slice底層是如何工作的非常重要,所以讓我們仔細査看究竟是發生了什麽。下面是第一個版本的appendInt函數,專門用於處理[]int類型的slice:</p>
|
|
<pre><code class="lang-Go">gopl.io/ch4/<span class="hljs-built_in">append</span>
|
|
|
|
<span class="hljs-keyword">func</span> appendInt(x []<span class="hljs-typename">int</span>, y <span class="hljs-typename">int</span>) []<span class="hljs-typename">int</span> {
|
|
<span class="hljs-keyword">var</span> z []<span class="hljs-typename">int</span>
|
|
zlen := <span class="hljs-built_in">len</span>(x) + <span class="hljs-number">1</span>
|
|
<span class="hljs-keyword">if</span> zlen <= <span class="hljs-built_in">cap</span>(x) {
|
|
<span class="hljs-comment">// There is room to grow. Extend the slice.</span>
|
|
z = x[:zlen]
|
|
} <span class="hljs-keyword">else</span> {
|
|
<span class="hljs-comment">// There is insufficient space. Allocate a new array.</span>
|
|
<span class="hljs-comment">// Grow by doubling, for amortized linear complexity.</span>
|
|
zcap := zlen
|
|
<span class="hljs-keyword">if</span> zcap < <span class="hljs-number">2</span>*<span class="hljs-built_in">len</span>(x) {
|
|
zcap = <span class="hljs-number">2</span> * <span class="hljs-built_in">len</span>(x)
|
|
}
|
|
z = <span class="hljs-built_in">make</span>([]<span class="hljs-typename">int</span>, zlen, zcap)
|
|
<span class="hljs-built_in">copy</span>(z, x) <span class="hljs-comment">// a built-in function; see text</span>
|
|
}
|
|
z[<span class="hljs-built_in">len</span>(x)] = y
|
|
<span class="hljs-keyword">return</span> z
|
|
}
|
|
</code></pre>
|
|
<p>每次調用appendInt函數,必鬚先檢測slice底層數組是否有足夠的容量來保存新添加的元素。如果有足夠空間的話,直接擴展slice(依然在原有的底層數組之上),將新添加的y元素複製到新擴展的空間,併返迴slice。因此,輸入的x和輸出的z共享相同的底層數組。</p>
|
|
<p>如果沒有足夠的增長空間的話,appendInt函數則會先分配一個足夠大的slice用於保存新的結果,先將輸入的x複製到新的空間,然後添加y元素。結果z和輸入的x引用的將是不同的底層數組。</p>
|
|
<p>雖然通過循環複製元素更直接,不過內置的copy函數可以方便地將一個slice複製另一個相同類型的slice。copy函數的第一個參數是要複製的目標slice,第二個參數是源slice,目標和源的位置順序和dst = src賦值語句是一致的。兩個slice可以共享同一個底層數組,甚至有重疊也沒有問題。copy函數將返迴成功複製的元素的個數(我們這里沒有用到),等於兩個slice中較小的長度,所以我們不用擔心覆蓋會超出目的slice的范圍。</p>
|
|
<p>爲了效率,新分配的數組一般略大於保存x和y所需要的最低大小。通過在每次擴展數組時直接將長度翻倍從而避免了多次內存分配,也確保了添加單個元素操的平均時間是一個常數時間。這個程序演示了效果:</p>
|
|
<pre><code class="lang-Go"><span class="hljs-keyword">func</span> main() {
|
|
<span class="hljs-keyword">var</span> x, y []<span class="hljs-typename">int</span>
|
|
<span class="hljs-keyword">for</span> i := <span class="hljs-number">0</span>; i < <span class="hljs-number">10</span>; i++ {
|
|
y = appendInt(x, i)
|
|
fmt.Printf(<span class="hljs-string">"%d cap=%d\t%v\n"</span>, i, <span class="hljs-built_in">cap</span>(y), y)
|
|
x = y
|
|
}
|
|
}
|
|
</code></pre>
|
|
<p>每一次容量的變化都會導致重新分配內存和copy操作:</p>
|
|
<pre><code>0 cap=1 [0]
|
|
1 cap=2 [0 1]
|
|
2 cap=4 [0 1 2]
|
|
3 cap=4 [0 1 2 3]
|
|
4 cap=8 [0 1 2 3 4]
|
|
5 cap=8 [0 1 2 3 4 5]
|
|
6 cap=8 [0 1 2 3 4 5 6]
|
|
7 cap=8 [0 1 2 3 4 5 6 7]
|
|
8 cap=16 [0 1 2 3 4 5 6 7 8]
|
|
9 cap=16 [0 1 2 3 4 5 6 7 8 9]
|
|
</code></pre><p>讓我們仔細査看i=3次的迭代。當時x包含了[0 1 2]三個元素,但是容量是4,因此可以簡單將新的元素添加到末尾,不需要新的內存分配。然後新的y的長度和容量都是4,併且和x引用着相同的底層數組,如圖4.2所示。</p>
|
|
<p><img src="../images/ch4-02.png" alt=""></p>
|
|
<p>在下一次迭代時i=4,現在沒有新的空餘的空間了,因此appendInt函數分配一個容量爲8的底層數組,將x的4個元素[0 1 2 3]複製到新空間的開頭,然後添加新的元素i,新元素的值是4。新的y的長度是5,容量是8;後面有3個空閒的位置,三次迭代都不需要分配新的空間。當前迭代中,y和x是對應不用底層數組的view。這次操作如圖4.3所示。</p>
|
|
<p><img src="../images/ch4-03.png" alt=""></p>
|
|
<p>內置的append函數可能使用比appendInt更複雜的內存擴展策略。因此,通常我們併不知道append調用是否導致了內存的分配,因此我們也不能確認新的slice和原始的slice是否引用的是相同的底層數組空間。同樣,我們不能確認在原先的slice上的操作是否會影響到新的slice。因此,通常是將append返迴的結果直接賦值給輸入的slice變量:</p>
|
|
<pre><code class="lang-Go">runes = <span class="hljs-built_in">append</span>(runes, r)
|
|
</code></pre>
|
|
<p>更新slice變量不僅對調用append函數是必要的,實際上對應任何可能導致長度、容量或底層數組變化的操作都是必要的。要正確地使用slice,需要記住盡管底層數組的元素是間接訪問,但是slice本身的指針、長度和容量是直接訪問的。要更新這些信息需要像上面例子那樣一個顯式的賦值操作。從這個角度看,slice併不是一個純粹的引用類型,它實際上是一個類似下面結構體的聚合類型:</p>
|
|
<pre><code class="lang-Go"><span class="hljs-keyword">type</span> IntSlice <span class="hljs-keyword">struct</span> {
|
|
ptr *<span class="hljs-typename">int</span>
|
|
<span class="hljs-built_in">len</span>, <span class="hljs-built_in">cap</span> <span class="hljs-typename">int</span>
|
|
}
|
|
</code></pre>
|
|
<p>我們的appendInt函數每次隻能向slice追加一個元素,但是內置的append函數則可以追加多個元素,甚至追加一個slice。</p>
|
|
<pre><code class="lang-Go"><span class="hljs-keyword">var</span> x []<span class="hljs-typename">int</span>
|
|
x = <span class="hljs-built_in">append</span>(x, <span class="hljs-number">1</span>)
|
|
x = <span class="hljs-built_in">append</span>(x, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>)
|
|
x = <span class="hljs-built_in">append</span>(x, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>)
|
|
x = <span class="hljs-built_in">append</span>(x, x...) <span class="hljs-comment">// append the slice x</span>
|
|
fmt.Println(x) <span class="hljs-comment">// "[1 2 3 4 5 6 1 2 3 4 5 6]"</span>
|
|
</code></pre>
|
|
<p>通過下面的小脩改,我們可以可以達到append函數類似的功能。其中在appendInt函數參數中的最後的“...”省略號表示接收變長的參數爲slice。我們將在5.7節詳細解釋這個特性。</p>
|
|
<pre><code class="lang-Go"><span class="hljs-keyword">func</span> appendInt(x []<span class="hljs-typename">int</span>, y ...<span class="hljs-typename">int</span>) []<span class="hljs-typename">int</span> {
|
|
<span class="hljs-keyword">var</span> z []<span class="hljs-typename">int</span>
|
|
zlen := <span class="hljs-built_in">len</span>(x) + <span class="hljs-built_in">len</span>(y)
|
|
<span class="hljs-comment">// ...expand z to at least zlen...</span>
|
|
<span class="hljs-built_in">copy</span>(z[<span class="hljs-built_in">len</span>(x):], y)
|
|
<span class="hljs-keyword">return</span> z
|
|
}
|
|
</code></pre>
|
|
<p>爲了避免重複,和前面相同的代碼併沒有顯示。</p>
|
|
<h3 id="422-slice內存技巧">4.2.2. Slice內存技巧</h3>
|
|
<p>讓我們看看更多的例子,比如镟轉slice、反轉slice或在slice原有內存空間脩改元素。給定一個字符串列表,下面的nonempty函數將在原有slice內存空間之上返迴不包含空字符串的列表:</p>
|
|
<pre><code class="lang-Go">gopl.io/ch4/nonempty
|
|
|
|
<span class="hljs-comment">// Nonempty is an example of an in-place slice algorithm.</span>
|
|
<span class="hljs-keyword">package</span> main
|
|
|
|
<span class="hljs-keyword">import</span> <span class="hljs-string">"fmt"</span>
|
|
|
|
<span class="hljs-comment">// nonempty returns a slice holding only the non-empty strings.</span>
|
|
<span class="hljs-comment">// The underlying array is modified during the call.</span>
|
|
<span class="hljs-keyword">func</span> nonempty(strings []<span class="hljs-typename">string</span>) []<span class="hljs-typename">string</span> {
|
|
i := <span class="hljs-number">0</span>
|
|
<span class="hljs-keyword">for</span> _, s := <span class="hljs-keyword">range</span> strings {
|
|
<span class="hljs-keyword">if</span> s != <span class="hljs-string">""</span> {
|
|
strings[i] = s
|
|
i++
|
|
}
|
|
}
|
|
<span class="hljs-keyword">return</span> strings[:i]
|
|
}
|
|
</code></pre>
|
|
<p>比較微妙的地方是,輸入的slice和輸出的slice共享一個底層數組。這可以避免分配另一個數組,不過原來的數據將可能會被覆蓋,正如下面兩個打印語句看到的那樣:</p>
|
|
<pre><code class="lang-Go">data := []<span class="hljs-typename">string</span>{<span class="hljs-string">"one"</span>, <span class="hljs-string">""</span>, <span class="hljs-string">"three"</span>}
|
|
fmt.Printf(<span class="hljs-string">"%q\n"</span>, nonempty(data)) <span class="hljs-comment">// `["one" "three"]`</span>
|
|
fmt.Printf(<span class="hljs-string">"%q\n"</span>, data) <span class="hljs-comment">// `["one" "three" "three"]`</span>
|
|
</code></pre>
|
|
<p>因此我們通常會這樣使用nonempty函數:data = nonempty(data)。</p>
|
|
<p>nonempty函數也可以使用append函數實現:</p>
|
|
<pre><code class="lang-Go"><span class="hljs-keyword">func</span> nonempty2(strings []<span class="hljs-typename">string</span>) []<span class="hljs-typename">string</span> {
|
|
out := strings[:<span class="hljs-number">0</span>] <span class="hljs-comment">// zero-length slice of original</span>
|
|
<span class="hljs-keyword">for</span> _, s := <span class="hljs-keyword">range</span> strings {
|
|
<span class="hljs-keyword">if</span> s != <span class="hljs-string">""</span> {
|
|
out = <span class="hljs-built_in">append</span>(out, s)
|
|
}
|
|
}
|
|
<span class="hljs-keyword">return</span> out
|
|
}
|
|
</code></pre>
|
|
<p>無論如何實現,以這種方式重用一個slice一般要求最多爲每個輸入值産生一個輸出值,事實上很多算法都是用來過濾或合併序列中相鄰的元素。這種slice用法是比較複雜的技巧,雖然使用到了slice的一些黑魔法,但是對於某些場合是比較清晰和有效的。</p>
|
|
<p>一個slice可以原來實現一個stack。最初給定的空slice對應一個空的stack,然後可以使用append函數將新的值壓入stack:</p>
|
|
<pre><code class="lang-Go">stack = <span class="hljs-built_in">append</span>(stack, v) <span class="hljs-comment">// push v</span>
|
|
</code></pre>
|
|
<p>stack的頂部位置對應slice的最後一個元素:</p>
|
|
<pre><code class="lang-Go">top := stack[<span class="hljs-built_in">len</span>(stack)-<span class="hljs-number">1</span>] <span class="hljs-comment">// top of stack</span>
|
|
</code></pre>
|
|
<p>通過收縮stack可以彈出棧頂的元素</p>
|
|
<pre><code class="lang-Go">stack = stack[:<span class="hljs-built_in">len</span>(stack)-<span class="hljs-number">1</span>] <span class="hljs-comment">// pop</span>
|
|
</code></pre>
|
|
<p>要刪除slice中間的某個元素併保存原有的元素順序,可以通過內置的copy函數將後面的子slice向前一位複雜完成:</p>
|
|
<pre><code class="lang-Go"><span class="hljs-keyword">func</span> remove(slice []<span class="hljs-typename">int</span>, i <span class="hljs-typename">int</span>) []<span class="hljs-typename">int</span> {
|
|
<span class="hljs-built_in">copy</span>(slice[i:], slice[i+<span class="hljs-number">1</span>:])
|
|
<span class="hljs-keyword">return</span> slice[:<span class="hljs-built_in">len</span>(slice)-<span class="hljs-number">1</span>]
|
|
}
|
|
|
|
<span class="hljs-keyword">func</span> main() {
|
|
s := []<span class="hljs-typename">int</span>{<span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>}
|
|
fmt.Println(remove(s, <span class="hljs-number">2</span>)) <span class="hljs-comment">// "[5 6 8 9]"</span>
|
|
}
|
|
</code></pre>
|
|
<p>如果刪除元素後不用保存原來順序的話,我們可以簡單的用最後一個元素覆蓋被刪除的元素:</p>
|
|
<pre><code class="lang-Go"><span class="hljs-keyword">func</span> remove(slice []<span class="hljs-typename">int</span>, i <span class="hljs-typename">int</span>) []<span class="hljs-typename">int</span> {
|
|
slice[i] = slice[<span class="hljs-built_in">len</span>(slice)-<span class="hljs-number">1</span>]
|
|
<span class="hljs-keyword">return</span> slice[:<span class="hljs-built_in">len</span>(slice)-<span class="hljs-number">1</span>]
|
|
}
|
|
|
|
<span class="hljs-keyword">func</span> main() {
|
|
s := []<span class="hljs-typename">int</span>{<span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>}
|
|
fmt.Println(remove(s, <span class="hljs-number">2</span>)) <span class="hljs-comment">// "[5 6 9 8]</span>
|
|
}
|
|
</code></pre>
|
|
<p><strong>練習 4.3:</strong> 重寫reverse函數,使用數組指針代替slice。</p>
|
|
<p><strong>練習 4.4:</strong> 編寫一個rotate函數,通過一次循環完成镟轉。</p>
|
|
<p><strong>練習 4.5:</strong> 寫一個函數在原地完成消除[]string中相鄰重複的字符串的操作。</p>
|
|
<p><strong>練習 4.6:</strong> 編寫一個函數,原地將一個UTF-8編碼的[]byte類型的slice中相鄰的空格(參考unicode.IsSpace)替換成一個空格返迴</p>
|
|
<p><strong>練習 4.7:</strong> 脩改reverse函數用於原地反轉UTF-8編碼的[]byte。是否可以不用分配額外的內存?</p>
|
|
|
|
|
|
</section>
|
|
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<a href="../ch4/ch4-01.html" class="navigation navigation-prev " aria-label="Previous page: 數組"><i class="fa fa-angle-left"></i></a>
|
|
|
|
|
|
<a href="../ch4/ch4-03.html" class="navigation navigation-next " aria-label="Next page: Map"><i class="fa fa-angle-right"></i></a>
|
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
<script src="../gitbook/app.js"></script>
|
|
|
|
|
|
<script src="../gitbook/plugins/gitbook-plugin-sharing/buttons.js"></script>
|
|
|
|
|
|
|
|
<script src="../gitbook/plugins/gitbook-plugin-fontsettings/buttons.js"></script>
|
|
|
|
|
|
<script>
|
|
require(["gitbook"], function(gitbook) {
|
|
var config = {"katex":{},"highlight":{},"sharing":{"facebook":true,"twitter":true,"google":false,"weibo":false,"instapaper":false,"vk":false,"all":["facebook","google","twitter","weibo","instapaper"]},"fontsettings":{"theme":"white","family":"sans","size":2}};
|
|
gitbook.start(config);
|
|
});
|
|
</script>
|
|
|
|
|
|
</body>
|
|
|
|
</html>
|