1. 程式人生 > >Go語言學習筆記(十)之切片

Go語言學習筆記(十)之切片

-h 種類 一個 fmt advance 小練習 輸出 程序 otto

15.切片

切片是基於數組類型做的一層封裝。它非常靈活,可以自動擴容。

切片的定義

  1: var a []int

// 定義一個int類型的空切片
// 切片不初始化是無法操作的,這點和數組不一樣。

切片的初始化:

  1: 1.arr[start:end]start到end-1(包括end-1)之間的所有元素
  2: 2.arr[start:]
  3: 3.arr[:end]
  4: 4.arr[:]包括整個數組的所有元素

例:

  1: a := [5]int{76,77,78,79,80}
  2: var b []int = a[1:4]
  3: c:= []int{6,7,8}

切片的修改:

  1: func main() {
  2: 	darr := [...]int{57,89,90,82,100,78,67,69,59}
  3: 	dslice := darr[2:5]
  4: 	fmt.Println("array before", darr)
  5: 	for i,_ := range dslice {
  6: 		dslice[i] ++
  7: 	}
  8: 	fmt.Println("array after", darr)
  9: }

//這種類似於python裏的淺拷貝

  1: func main() {
  2: 	numa := [3]int{78,79,80}
  3: 	nums1 := numa[:]
  4: 	nums2 := numa[:]
  5: 	fmt.Println("array before change 1", numa)
  6: 	nums1[0] = 100
  7: 	fmt.Println(numa)
  8: 	nums2[1] = 101
  9: 	fmt.Println(numa)
 10: }
 11: >>> [100 79 80]
 12: [100 101 80]

使用make創建切片

  1: i := make([]int, 5, 5)

// (類型 當前長度 容量上線)
// 未指定的元素默認為0

  1: func main() {
  2: 	var a []int
  3: 	a = make([]int, 1, 10)
  4: 	a[0] = 10
  5: 	// 這裏a[1] = 20 會報錯,操作越界了,這是個重要的細節,忽略很容易犯錯
  6: 	a = append(a, 11)
  7: 	fmt.Printf(a)
  8: }
  1: >>> [10 11]

擴容(cap(a)是表示a的容量上限)

  1: for i:=0;i<10;i++ {
  2: 	a = append(a, i)
  3: 	fmt.Printf("a=%v addr:%p len:%d cap:%d\n", a,a,len(a),cap(a))
  4: }

輸出:

  1: >>>a=[10 11 0] addr:0xc000014140 len:3 cap:10
  2: a=[10 11 0 1] addr:0xc000014140 len:4 cap:10
  3: a=[10 11 0 1 2] addr:0xc000014140 len:5 cap:10
  4: a=[10 11 0 1 2 3] addr:0xc000014140 len:6 cap:10
  5: a=[10 11 0 1 2 3 4] addr:0xc000014140 len:7 cap:10
  6: a=[10 11 0 1 2 3 4 5] addr:0xc000014140 len:8 cap:10
  7: a=[10 11 0 1 2 3 4 5 6] addr:0xc000014140 len:9 cap:10
  8: a=[10 11 0 1 2 3 4 5 6 7] addr:0xc000014140 len:10 cap:10
  9: a=[10 11 0 1 2 3 4 5 6 7 8] addr:0xc00008a000 len:11 cap:20

//觀察擴容的結果,發現擴容的策略是翻倍擴容

  1: func testCap() {
  2: 	a := [...]string{"a","b","c","d","e","f","g","h"}
  3: 	b := a[1:3]
  4: 	fmt.Printf("b:%v len:%d cap:%d\n",b,len(b),cap(b))
  5: }
  1: >>> b:[b c] len:2 cap:7 

空切片

  1: var a []int
  2: fmt.Println(a, len(a), cap(a))
  3: a = append(a, 100)
  4: fmt.Println(a, len(a), cap(a))
  1: >>> [] 0 0
  2: [100] 1 1

切片傳參

  1: veggies := []string{"potatoes", "tomatoes", "brinjal"}
  2: fruits := []string{"oranges", "apples"}
  3: food := append(veggies, fruits...)
  4: // friuts後面的3個點表示展開fruits切片成一個個元素
  5: fmt.Println(food)
  1: func modifySlice(a []int) {
  2: 	a[0] = 1000
  3: }
  4: func main(){
  5: 	var a [3]int = [3]int{1, 2, 3}
  6: 	modifySlice(a[:])
  7: 	fmt.Println(a)
  8: }
  1: >>> [1000, 2, 3]

切片的拷貝

  1: func main() {
  2: 	veggies := []string{"potatoes", "tomatoes", "brinjal"}
  3: 	fruits := []string{"oranges", "apples"}
  4: 	copy(veggies, fruits)
  5: 	fmt.Println(veggies, fruits)
  6: }
  1: >>> [oranges apples brinjal] [oranges apples]
  1: func main() {
  2: 	var a := []int{1, 2}
  3: 	var a = []int{1, 2}
  4: 	var b := []int{4, 5, 6}
  5: 	copy(a, b)
  6: 	fmt.Println(a, b)
  7: }
  1: >>> [4 5] [4 5 6]

make和new的區別

make為內建類型為slice, map和channel分配內存
new用於各種類型的內存分配, new返回的是一個指針

幾個小練習

1.下面程序輸出什麽

  1: func main() {
  2: 	var a = make([]string, 5, 10);
  3: 	for i:=0;i<10;i++{
  4: 		a = append(a, fmt.Sprintf("%d", i))
  5: 	}
  6: 	fmt.Println(a)
  7: }
  1: >>> a= [    ]
  2: a= [     0 1 2 3 4 5 6 7 8 9]

2.使用golang標準包"sort"對數組進行排序

  1: func main() {
  2: 	a := []int{5, 4, 3, 2, 1}
  3: 	sort.Ints(a[:])
  4: 	fmt.Println("a=",a)
  5: 	b := []string{"f", "e", "c", "b", "a"}
  6: 	sort.Strings(b[:])
  7: 	fmt.Println("b=",b)
  8: 	c := []float64{58.554,88.23,998.255,48.25,566.66}
  9: 	sort.Float64s(c[:])
 10: 	fmt.Println("c=",c)
 11: }

3.實現一個密碼生成工具,支持以下功能
PS:標準包"flag"解析命令行參數
a.用戶可以通過-l指定生成讓那個密碼的長度
b.用戶可以通過-t指定生成密碼的字符集,比如-t num生成全數字的密碼-t char生成包含全英文字符的密碼, -t mix包含生成數字和英文的密碼,-t advance生成包含數字,英文以及特殊字符的密碼

  1: package main
  2: 
  3: import (
  4: 	"fmt"
  5: 	"flag"
  6: 	"math/rand"
  7: 	"time"
  8: )
  9: var (
 10: 	length int
 11: 	charset string
 12: )
 13: const (
 14: 	NumStr = "0123456789"
 15: 	CharStr = "abcdefghjkmnopqrstuvwxyzABCDEFGHJKMNOPQRSTUVWXYZ"
 16: 	SpecStr = "@#$%^&*_+=/*-"
 17: )
 18: func parseArgs() {
 19: 	flag.IntVar(&length, "l", 16, "-l 生成密碼長度")
 20: 	flag.StringVar(&charset, "t", "num", 
 21: 	`-t 制定密碼生成的字符集, 
 22: 	num:只使用數字[0-9],
 23: 	char:只使用英文字母[a-zA-Z],
 24: 	mix:使用數字和字母,
 25: 	advance:使用數字字母以及特殊字符`)
 26: 	flag.Parse()
 27: }
 28: func generatePasswd() string {
 29: 	var password []byte = make([]byte, length, length)
 30: 	var sourceStr string
 31: 	if charset == "num" {
 32: 		sourceStr = NumStr
 33: 	}else if charset == "char"{
 34: 		sourceStr = CharStr
 35: 	}else if charset == "mix" {
 36: 		sourceStr = fmt.Sprintf("%s%s", NumStr, CharStr)
 37: 	}else if charset == "advance" {
 38: 		sourceStr = fmt.Sprintf("%s%s%s", NumStr, CharStr, SpecStr)
 39: 	}else {
 40: 		sourceStr = NumStr
 41: 	}
 42: 	fmt.Println("sourceStr:", sourceStr)
 43: 	for i:=0;i<length;i++{
 44: 		index := rand.Intn(len(sourceStr))
 45: 		password[i] = sourceStr[index]
 46: 	}
 47: 	return string(password)
 48: }
 49: func main() {
 50: 	rand.Seed(time.Now().UnixNano())
 51: 	parseArgs()
 52: 	fmt.Printf("length:%d charset:%s\n", length, charset)
 53: 	passwd := generatePasswd()
 54: 	fmt.Println(passwd)
 55: }

編譯後輸入:

  1: main.exe -l 45 -t num

結果

  1: length:45 charset:num
  2: sourceStr: 0123456789
  3: 263415358329572320363459838031515468782761014

Go語言學習筆記(十)之切片