golang基礎篇

一、切片:

1、主要看指針指向位置
比如 一個切片 var s []int{1,2,3,4,5,6,7}
指針指向0位
長度是 7 ,容量是7
a := s[2:4]
指針指向index爲2爲
a 長度是 2 (元素是2,3) 容量是5 (從index爲2往右算或者max_len 減去 開始index,即 7 -2 = 5

 

二、defer
延遲處理
執行機制: 在函數內先實例(這在defer函數裏包含函數參數有用,比如 defer func(int,int,func()),先執行裏面的func),然後待執行完函數後,多個defer再按照
LIFO(後進先執行)原則執行。
還有一點需要注意,defer在實例時,它的參數是已確定,比如在defer前面定義了參數a = 1,在defer 後面再重新賦值a = 10,在執行defer時是按a=1傳進defer的。

func calc(index string, a, b int) int {
ret := a + b
fmt.Println(index, a, b, ret)
return ret
}

func main() {
x := 1
y := 2
defer calc("AA", x, calc("A", x, y))
x = 10
defer calc("BB", x, calc("B", x, y))
y = 20
fmt.Println("dfdff")
}

 

 

三、指針

&在變量前,取的是指針變量(即內存地址)

a := 10
b := &a //獲取到a變量的內存地址,類型是 int的指針類型: *int
c := b //通過對指針變量進行取值操作,獲取指針變量指向的原變量的值

關鍵字 new , make
new : func new(Type) *Type
在聲明類型指針變量時,因爲爲引用類型,所以需要初始化後纔有內存空間,才能進行賦值
var a *int
a = new(int)
*a = 10
fmt.Println(a)

make: func make(t Type, size ...IntegerType) Type
make只適用slice、map、chan
make函數是無可替代的,我們在使用slice、map以及channel的時候,都需要使用make進行初始化,然後纔可以對它們進行操作。
func main() {
var b map[string]int
b = make(map[string]int, 10)
b["沙河娜扎"] = 100
fmt.Println(b)
}
new與make的區別:
1、二者都是用來做內存分配的。
2、make只用於slice、map以及channel的初始化,返回的還是這三個引用類型本身;
3、而new用於類型的內存分配,並且內存對應的值爲類型零值,返回的是指向類型的指針。

 

 

四、結構體(struct)
type 類型名 struct {
字段名 字段類型
字段名 字段類型

}
結構體本身也是一種類型,我們可以像聲明內置類型一樣使用var關鍵字聲明結構體類型。
基本例子:

type person struct {
name string
city string
age int8
}

func main() {
	var p1 person
	p1.name = "沙河娜扎"
	p1.city = "北京"
	p1.age = 18
	fmt.Printf("p1=%v\n", p1)  //p1={沙河娜扎 北京 18}
	fmt.Printf("p1=%#v\n", p1) //p1=main.person{name:"沙河娜扎", city:"北京", age:18}
}

可以通過使用new關鍵字對結構體進行實例化,得到的是結構體的地址。 格式如下:
var p2 = new(person)
fmt.Printf("%T\n", p2)     //*main.person
fmt.Printf("p2=%#v\n", p2) //p2=&main.person{name:"", city:"", age:0}
p2是一個結構體
Go語言中支持對結構體指針直接使用.來訪問結構體的成員。
var p2 = new(person)
p2.name = "小王子"
p2.age = 28
p2.city = "上海"
fmt.Printf("p2=%#v\n", p2) //p2=&main.person{name:"小王子", city:"上海", age:28}
p2.age = 28 其實在底層是(p2).age = 28,這是go語言幫助我們實現的語法糖。

  

 

五、構造函數
Go語言的結構體沒有構造函數,我們可以自己實現。 例如,下方的代碼就實現了一個person的構造函數。 因爲struct是值類型,如果結構體比較複雜的話,值拷貝性能開銷會比較大,所以該構造函數返回的是結構體指針類型。

func newPerson(name, city string, age int8) *person {
return &person{
name: name,
city: city,
age: age,
}
}

調用構造函數
p9 := newPerson("張三", "沙河", 90)
fmt.Printf("%#v\n", p9) //&main.person{name:"張三", city:"沙河", age:90}

  

 

六、方法
方法是一種作用於特定類型變量的函數,類似其他語言的this或self,定義如下:
func (接收者變量 接收者類型) 方法名(參數列表) (返回參數) {
函數體
}
一般接收者變量名是接收類型的名字首位小寫,如結構體Person,它的接收者名爲p。
例子:

//Person 結構體
type Person struct {
name string
age int8
}

	//NewPerson 構造函數
	func NewPerson(name string, age int8) *Person {
		return &Person{
			name: name,
			age:  age,
		}
	}

	//Dream Person做夢的方法
	func (p Person) Dream() {
		fmt.Printf("%s的夢想是學好Go語言!\n", p.name)
	}

	func main() {
		p1 := NewPerson("小王子", 25)
		p1.Dream()
	}

 方法與函數的區別是,函數不屬於任何類型,方法屬於特定的類型。

 

七、channel

channel 是遵循FIFO原則,有個例子,當配合goroutine(開線程)使用,多個channel讀取時,會實時根據當前讀取的cha1,cha1存多少被讀取的就有多少。

例子:

`package main

import(
"fmt"
"time"
)

func recv(ch chan int) {
for i := 0;i<3;i++ {
fmt.Println(i)
time.Sleep(time.Second)
ch <- i //傳送值給cha1
}
close(ch)
fmt.Println("ppppppp")
}

func recv2(ch1 chan int,ch2 chan int) {
for {
tmp,ok := <-ch1
fmt.Println(tmp)
if !ok{
break
}
ch2 <- tmp*tmp
}
close(ch2)
fmt.Println("kkssk")
}

func main() {
cha1 := make(chan int, 100) //初始化一個channel
cha2 := make(chan int, 200) // 初始化另一個channel

go recv(cha1)
go recv2(cha1, cha2)

for tt := range cha2 {
	fmt.Println(tt)
}
}`

  

待續~

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章