golang高級語法及特點

golang高級語法及特點

golang特點
  • 枚舉類型 iota
  • 沒有char 只有rune
  • go語言所有類型都有默認值
  • 原生支持複數類型
  • switch後可以沒有表達式
  • 只有for 沒有while for可以不要條件 可以只有退出條件
  • 函數沒有缺省參數
  • 數組是值類型,調用func f(arr [10]int)會 拷貝 數組
  • go只有值傳遞沒有引用傳遞, 所以用指針類型來補充其他語言的引用傳遞
  • rune相當於go的char 使用utf8編碼,中文佔3個字節,英文一個字節
rune
package main

import "fmt"

//rune相當於go的char  使用utf8編碼,中文佔3個字節,英文一個字節

func main() {
	s:= "ok我愛你"
	fmt.Println(len(s))    // 11
	fmt.Println(len([]rune(s)))  // 5
	fmt.Println(len([]byte(s)))  // 11

	// str是int32類型
	for i, str := range s {
		fmt.Printf("%d %c", i, str)
		fmt.Println()
	}

	// str是byte類型
	for i, str := range []byte(s) {
		fmt.Printf("%d %x", i, str)
		fmt.Println()
	}

	// str是rune類型
	for i, str := range []rune(s) {
		fmt.Printf("%d %c", i, str)
		fmt.Println()
	}


}

slice切片
  • slice的底層是數組
  • slice是對數組的view
  • slice可以向後擴展,不可以向前擴展
  • s[i]不可以超過len(s), 向後擴展不可以超越底層數組cap(s)
  • slice內部維持了3個變量,ptr指針指向slice的第一個元素,len指定了slice的長度,cap指定了slice的容量。
  • slice進行append時,容量不夠會進行翻倍。
有如下
arr := [...]{0, 1, 2, 3, 4, 5, 6, 7}
s1 := arr[2:6]
s2 := s1[3:5]
則
s1值爲[2,3,4,5],  len(s1)=4, cap(s1)=6 
s2值爲[5,6], len(s2)=2, cap(s2)=3
slice底層是數組
slice可以向後擴展,不可以向前擴展
s[i]不可以超過len(s), 向後擴展不可以超越底層數組cap(s)

接着上題
arr := [...]{0, 1, 2, 3, 4, 5, 6, 7}
s1 := arr[2:6]
s2 := s1[3:5]
s3 := append(s2, 10)
s4 := append(s3, 11)
s5 := append(s4, 12)
則
s1值爲[2,3,4,5]
s2值爲[5,6]
s3值爲[5,6,10]
s4值爲[5,6,10,11]
s5值爲[5,6,10,11,12]
arr值爲[0, 1, 2, 3, 4, 5, 6, 10]

由於s4和時s5已經超過arr的cap,此時系統會生成一個新的數組,所以s4和s5是對新數組的view,即s4和s5 no longer view arr
  • 添加元素時如果超越cap,系統會重新分配更大的底層數組,原來的數組被拷貝過去,如果原來的數組沒人用則會被gc
  • 由於值傳遞的關係,必須接受append的返回值
map
  • go語言所以類型都有默認值
  • 當map取值的key不存在時,只會返回默認值,不會報錯。判斷key存不存在用 key, ok := m[“key”]
  • map使用哈希表,作爲map的key必須可以比較相等
  • 除了slice,map, function的內建類型都可以作爲key
  • struce類型不包含上述字段,也可以作爲key
struct
  • 只有使用指針纔可以改變結構體內容
  • nil指針也可以調用方法
  • 如何擴充系統類型或者別人的類型:通過結構體繼承,通過類型起別名
package main


// 如何擴充系統類型或者別人的類型:通過結構體繼承,通過類型起別名
type queue []int

func (q *queue) push(v int) {
	*q = append(*q, v)
}

func (q *queue) pop() int {
	head := (*q)[0]
	*q = (*q)[1:]
	return head
}

func (q *queue) isEmpty() bool {
	return len(*q) == 0
}




func main() {

}

  • 值接受者vs指針接受者,
  •   值接受者是go語言特有
    
  •   要改變內容必須使用指針接受者,
    
  •   結構過大也考慮使用指針接受者。
    
  •   值/指針接受者都可以調用值/指針調用
    
package main

import "fmt"

type node struct {
	value int
	left, right *node
}

func newNode(value int) *node{
	return &node{
		value: value,
		left:  nil,
		right: nil,
	}
}

func (n node) setVal(val int) {
	n.value = val
}

func (n *node) setValue(vall int) {
	n.value = vall
}

func (n node) print() {
	fmt.Println(n.value)
}

func (n *node) travel() {
	if n == nil {
		return
	}

	fmt.Println(n.value)
	n.left.travel()
	n.right.travel()
}

func main() {

	var root node
	root = node{}
	root.left = &node{value:5}
	root.right = new(node)
	root.left.right = &node{4, nil, nil}
	root.right.left = newNode(7)
	
	// 調用指針方法,相當於引用傳遞,可以改變外部的值
	root.left.setValue(100)
	fmt.Println(root.left.value)
	
	// 值傳遞,調用值方法,方法內部不能改變外部值
	root.left.setVal(99)
	fmt.Println(root.left.value)
	
	// 先序遍歷
	root.travel()
}

interface
  • 多用接口組合
defer
  • panic和return都不影響defer的調用
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章