1、指針類型golang
一、普通類型,變量存的就是值,也叫值類型。指針類型存的是地址數據庫
二、獲取變量的地址,用&,好比:var a int, 獲取a的地址 &a數組
三、指針類型,變量存的是一個地址,這個地址存的纔是值閉包
四、獲取指針類型所指向的值,使用:* ,好比:var p *int,使用*p獲取p指向的變量的值app
var a int = 5 函數
var p *int = &a 0xefefefe 指向變量a的值是 5性能
五、指針類型的變量初始話有兩種:設計
5.一、直接給指針賦值其餘變量的地址指針
func test3(){
var p *int //默認初始化nil
var a int
p = &a
*p = 200
fmt.Println(a)
}
5.二、使用new分配對象
func test4(){
var p *int
p = new(int)
*p = 2000
fmt.Println(*p)
}
六、練習題
6.一、練習1:寫一個程序,獲取一個變量的地址,並打印到終端
package main
import (
"fmt"
)
func test1(){
var a int = 5
var p *int = &a
fmt.Printf("a的地址是:%p\n",p)
fmt.Printf("a的值是:%d",*p)
}
func main(){
test1()
}
運行打印的結果以下:
6.二、練習2:寫一個函數,傳入一個int類型的指針,並在函數中修改所指向的值
func modify(x *int){ //傳入的變量x類型是指針 *int表明指針是整形的指針
*x = 200 //給x指針指向的值從新賦值爲200
}
func test2(){
var a int = 5 //定義一個整形的變量a,初始值是5
var p *int = &a //定義一個指針p,指向的是a
fmt.Println("變量a的初始值是",a) //打印a的初始值
modify(p) //修改p指針指向的a的值
fmt.Println("p指針指向的a變量的改變值是",a) //打印a的值改變的結果
}
func main(){
test2()
}
執行打印的結果以下:
2、內置函數
一、close:主要用來關閉channel
二、len:用來求長度,好比string、array、slice、map、channel
三、new:用來分配內存,主要用來分配值類型,好比int、struct。返回的是指針。示例能夠看上面一的5.2,
四、make:用來分配內存,主要用來分配引用類型,好比channel、map、slice
五、append:用來追加元素到數組、slice中
六、panic和recover:用來作錯誤處理
七、new和make的區別
7.一、內建函數 new 用來分配內存,它的第一個參數是一個類型,不是一個值,它的返回值是一個指向新分配類型零值的指針
7.二、內建函數 make 用來爲 slice,map 或 chan 類型分配內存和初始化一個對象(注意:只能用在這三種類型上),跟 new 相似,第一個參數也是一個類型而不是一個值,跟 new 不一樣的是,make 返回類型的引用而不是指針,而返回值也依賴於具體傳入的類型,具體說明以下:
Slice: 第二個參數 size 指定了它的長度,它的容量和長度相同。
你能夠傳入第三個參數來指定不一樣的容量值,但必須不能比長度值小。
好比 make([]int, 0, 10)
Map: 根據 size 大小來初始化分配內存,不過度配後的 map 長度爲 0,若是 size 被忽略了,那麼會在初始化分配內存時分配一個小尺寸的內存
Channel: 管道緩衝區依據緩衝區容量被初始化。若是容量爲 0 或者忽略容量,管道是沒有緩衝區的
7.三、總結:
new 的做用是初始化一個指向類型的指針(*T),make 的做用是爲 slice,map 或 chan 初始化並返回引用(T)。
3、函數
一、聲明語法:func 函數名(參數列表)[(返回值列表)]{}
func add(){
}
func add(a int,b int){
}
func add(a int, b int) int {
}
func add(a int, b int) (int , int){
}
func add(a , b int) (int , int){
}
二、golang函數的特色:
a、不支持重載,一個包不能有兩個名字同樣的函數;
b、函數是一等公民,函數也是一種類型,函數也能夠賦值給變量
c、匿名函數
d、多返回值
示例:
type add_func func(int, int)int
func oprator(op add_func,a int,b int)int {
//使用傳進來的函數op,進行操做
return op(a,b)
}
func add(a,b int) int {
return a + b
}
func main(){
c:=add
fmt.Println(c)
sum := oprator(c,100,200)
}
三、函數參數傳遞方式:
3.一、值傳遞
3.二、引用傳遞
注意1:不管是值傳遞,仍是引用傳遞,傳遞給函數的都是變量的副本。值傳遞是值的拷貝,通常來講地址拷貝更高效。值拷貝取決於拷貝的對象的大小,對象越大,性能越低。
注意2:map、slice、channel、指針、interface默認以引用的方式傳遞
func reduce(a , b int)(c int){
c = a - b
return
}
//重命名多個返回值
func calc(a,b int)(sum int,avg int){
sum = a + b
avg = sum/2
return
}
// _ 忽略返回值
func main(){
sum,_ := calc(100,200)
}
五、可變參數:
多個參數
func test11(arg...int) int{
}
一個或多個參數
func test11(a int ,arg...int) int{
}
二個或多個參數
func test11(a int,b int ,arg...int) int{
}
注意:其中arg是一個slice,咱們能夠經過arg[index]來獲取多個參數
經過len(arg)來判斷傳遞參數的個數
六、練習題示例
package main
import (
"fmt"
)
//練習題一:寫一個函數add,支持1個或多個int相加,並返回結果
func add(a int,arg...int)int{
var sum int
//當只有一個參數時
if len(arg)==0{
sum = a
}
//當參數大於一個時
if len(arg)>0{
for i:=0;i<len(arg);i++{
//注意這裏但arg裏面只有一個參數時,i是等於0即arg[0]
if i == 0 {
sum = a + arg[0]
}
//當arg參數大於一個時
if i >0 {
sum+=arg[i]
}
}
}
return sum
}
//練習題二:寫一個函數concat,支持1個或多個string相拼接,並返回結果
func concat(a string,arg...string)string{
var str string
if len(arg)==0{
str = a
}
if len(arg)>0{
for i:=0;i<len(arg);i++{
if i == 0 {
str = a + arg[0]
}
if i >0 {
str+=arg[i]
}
}
}
return str
}
func main(){
fmt.Println(add(-22,23,555))
fmt.Println(concat("aaa","bbbbb","ccccccc"))
}
七、defer的特色和用途
7.一、當函數返回時,執行defer語句。所以能夠用來作資源清理
7.二、多個defer語句,按先進後出的方式執行
示例:
func a(){
fmt.Println("defer from a")
i:=0
defer fmt.Println(i) //defer語句中的變量,在defer聲明時就決定
i++
}
func f(){
fmt.Println("defer from f")
for i:=0;i<5;i++{
defer fmt.Println(i)
}
}
func main(){
//練習三
a()
f()
}
打印的結果:
7.三、defer語句中的變量,在defer聲明時就決定了
7.四、defer用途:關閉文件句柄,鎖資源釋放,數據庫鏈接釋放
4、遞歸函數
一、一個函數調用本身,就叫遞歸函數
二、斐波那契數
//斐波那契數列示例:
func fb( n int)int{
if n <=1{
return 1
}
return fb(n-1)+fb(n-2)
}
func main(){
for i:=0;i<10;i++{
n := fb(i)
fmt.Println(n)
}
}
三、遞歸的設計原則
3.一、一個大問題可以分解成類似的小問題
3.二、定義好出口條件(即結束遞歸循環的條件)
5、閉包
一個函數和與其相關的引用環境的組合成的實體
//示例一:
func Adder() func(int)int{
var x int
return func(delta int)int{
x +=delta
return x
}
}
//示例2:
func makeSuffixFunc(suffix string) func(string)string{
return func(name string)string{
if !strings.HasSuffix(name ,suffix){
return name + suffix
}
return name
}
}
func main(){
//練習五:閉包
//示例1:
// var f = Adder()
// fmt.Println(f(1))
// fmt.Println(f(10))
// fmt.Println(f(100))
//示例2:
func1 := makeSuffixFunc(".jpg")
func2 := makeSuffixFunc(".txt")
fmt.Println(func1(func1("test")))
fmt.Println(func2("test"))
}
6、數組和切片
1.一、排序和查找操做
排序操做主要都在sort包中,導入就可使用
sort.Ints對整數進行排序, sort.Strings對字符串串進⾏行行排序, sort.Float64s對 浮點數進⾏行行排序.
sort.SearchInts(a []int, b int) 從數組a中查找b,前提是a 必須有序
sort.SearchFloats(a []float64, b float64) 從數組a中查找b,前提是a 必須有序
sort.SearchStrings(a []string, b string) 從數組a中查找b,前提是a 必須有序