### append
向原切片末尾添加元素,并返回新的切片對象.
~~~
s := []int{}
fmt.Println(s, len(s), cap(s))
s = append(s, 1)
s = append(s, 2)
fmt.Println(s, len(s), cap(s))
s1 :=[]int{1,2,3}
s1 = append(s1,100)
fmt.Println(s1)
~~~
~~~
[] 0 0
[1 2] 2 2
[1 2 3 100]
~~~
### append擴容特點
函數 append 會智能地處理底層數組的容量增長。在切片的容量小于 1000 個元素時,總是
會成倍地增加容量。一旦元素個數超過 1000,容量的增長因子會設為 1.25,也就是會每次
增加 25%的容量。隨著語言的演化,這種增長算法可能會有所改變
~~~
s := make([]int, 0, 1)
fmt.Println(s, len(s), cap(s))
oldCap := cap(s)
for i := 0; i < 17; i++ {
s = append(s, i)
if newCap := cap(s); oldCap < newCap {
fmt.Println("當前長度", len(s),"新容量", newCap)
}
}
~~~
~~~
[] 0 1
當前長度 2 新容量 2
當前長度 3 新容量 4
當前長度 4 新容量 4
當前長度 5 新容量 8
當前長度 6 新容量 8
當前長度 7 新容量 8
當前長度 8 新容量 8
當前長度 9 新容量 16
當前長度 10 新容量 16
當前長度 11 新容量 16
當前長度 12 新容量 16
當前長度 13 新容量 16
當前長度 14 新容量 16
當前長度 15 新容量 16
當前長度 16 新容量 16
當前長度 17 新容量 32
~~~
**注意: 使用append向容量也使用了底層數組的切片添加元素也會改變底層數組的值**
~~~
slice := []int{10, 20, 30, 40, 50}
newSlice := slice[1:3]
fmt.Println(newSlice, len(newSlice), cap(newSlice))
newSlice = append(newSlice, 60)
fmt.Println(newSlice, len(newSlice), cap(newSlice))
fmt.Println(slice, len(slice), cap(slice))
~~~
~~~
[20 30] 2 4
[20 30 60] 3 4
[10 20 30 60 50] 5 5
~~~
### 創建切片時的第三個索引
~~~
在創建切片時,還可以使用之前我們沒有提及的第三個索引選項。第三個索引可以用來控制新
切片的容量。其目的并不是要增加容量,而是要限制容量。可以看到,允許限制新切片的容量
為底層數組提供了一定的保護,可以更好地控制追加操作. *如果在創建切片時設置切片的容量
和長度一樣,就可以強制讓新切片的第一個 append 操作創建新的底層數組,與原有的底層數
組分離。新切片與原有的底層數組分離后,可以安全地進行后續修改.*
~~~
~~~
slice := []int{10, 20, 30, 40, 50}
newSlice := slice[1:3:3]
fmt.Println(newSlice, len(newSlice), cap(newSlice))
newSlice = append(newSlice, 100)
fmt.Println(slice, len(slice), cap(slice))
fmt.Println(newSlice, len(newSlice), cap(newSlice))
~~~
**因為限制了容量,所以沒有對底層數組的元素也進行修改**
~~~
[20 30] 2 2
[10 20 30 40 50] 5 5
[20 30 100] 3 4
~~~
### ...運算符
使用...運算符可以將一個切片的所有元素添加到另一個元素當中
~~~
s1 := []int{10, 20, 30, 40, 50}
s2 := []int{90, 100}
fmt.Println(append(s1, s2...))
~~~
~~~
[10 20 30 40 50 90 100]
~~~
### copy
~~~
s1 := []int{1, 2, 3}
s2 := []int{4, 5, 6, 7, 8, 9}
copy(s2, s1) //前面是目標切片
fmt.Println(s2)
~~~
~~~
[1 2 3 7 8 9]
~~~
- 基本語法
- 申明變量
- 常量
- 數據類型
- 強制類型轉換
- 獲取命令行參數
- 指針
- 概述
- new函數
- 函數
- 概述
- 不定參數類型
- 有返回值
- 函數類型
- 回調函數
- 匿名函數和閉包
- 延遲調用defer
- 工程管理
- 工作區
- src,pkg和bin目錄
- 復合類型
- 概述
- 數組
- 概述
- 聲明并初始化
- 拷貝傳值
- slice
- 概述
- 創建切片
- 切片截取
- 切片和底層數組的關系
- slice常用方法
- 切片做函數參數
- map
- 概述
- map操作
- 結構體
- 概述
- 結構體初始化
- 結構體比較
- 結構體作為函數參數
- 結構體前加&
- 面向對象
- 概述
- 匿名組合
- 方法
- 值語義和引用語義
- 方法集
- 方法的繼承
- 方法重寫
- 方法值
- 接口
- 接口定義和實現
- 多態的表現
- 接口繼承
- 接口轉換
- 空接口
- 類型斷言
- 異常處理
- error接口
- panic
- recover
- 文本文件處理
- 字符串操作
- 正則表達式
- json處理
- 文件操作
- 標準設備文件操作
- 并發編程
- 概述
- 并發和并行
- go語言并發優勢
- goroutine
- goroutine概述
- 創建goroutine
- 主協程先退出
- runtime包
- Gosched
- Goexit
- GOMAXPROCE
- channel
- 多資源競爭
- channel類型
- 無緩沖channel
- 有緩沖channel
- 關閉channel
- 單向channel
- 單向channel特性
- 定時器
- Timer
- Ticker
- select
- select作用
- 超時
- sync
- 競爭狀態
- 網絡編程
- 網絡概述
- 網絡協議
- 分層模型
- 網絡分層架構
- 層與協議
- 每層協議的功能
- 鏈路層
- 網絡層
- 傳輸層
- 應用層
- socket編程
- 組合和繼承
- 注意事項
- 細節
- go語言實現隊列
- google工程師golang
- 基礎語法
- 內建容器
- 面向"對象"
- 依賴管理
- 面向接口
- 函數式編程
- 錯誤處理和資源管理
- 測試與性能調優
- goroutine
- channel
- golang問題集
- 斷言和類型轉換
- Go語言圣經
- 入門
- 程序結構
- 命名
- 聲明
- 變量
- 賦值
- 類型
- 包和文件
- 作用域
- 基礎數據類型
- 整數
- 浮點數
- 復數
- 布爾型
- 字符串
- 常量
- 復合數據類型
- 數組
- slice
- map
- 結構體
- json
- 文本和HTML模板
- 函數
- 函數聲明
- 錯誤
- 函數值
- 匿名函數
- defer
- panic
- recover
- 方法
- 方法聲明
- 指針對象的方法
- 封裝
- 接口
- 說明
- 接口是合約
- 實現接口的條件
- 接口值
- 類型斷言
- 通過類型斷言詢問行為
- 類型開關
- Goroutines和Channels
- 協程
- channels
- 無緩沖channel
- 串聯的channel
- 有緩沖channel
- 并發的循環
- select多路復用
- 并發的退出
- 并發問題的自我思考
- 基于共享變量的并發
- 競爭條件
- 互斥鎖
- 讀寫鎖
- 內存同步
- sync.Once
- 協程和線程
- 包和工具
- 測試
- 反射
- 什么是反射
- 為什么需要反射
- reflect.Type和reflect.Value
- 通過reflect.Value修改值
- 底層編程