函數的基本概念
為完成某一功能的程序指令(語句)的集合,稱為函數。
在 Go 中,函數分為: 自定義函數、系統函數(查看 Go 編程手冊)
函數的基本語法

快速入門案例

包
包的引出
1)在實際的開發中,我們往往需要在不同的文件中,去調用其它文件的定義的函數,比如 main.go中,去使用 utils.go 文件中的函數,如何實現? -》包
2)現在有兩個程序員共同開發一個 Go 項目,程序員 xiaoming 希望定義函數 Cal ,程序員 xiaoqiang也想定義函數也叫 Cal。兩個程序員為此還吵了起來,怎么辦? -》包
包的原理圖
包的本質實際上就是創建不同的文件夾,來存放程序文件。畫圖說明一下包的原理

包的基本概念
說明:go 的每一個文件都是屬於一個包的,也就是說 go 是以包的形式來管理文件和項目目錄結構的
包的三大作用
區分相同名字的函數、變量等標識符
當程序文件很多時,可以很好的管理項目
控制函數、變量等訪問范圍,即作用域
包的相關說明
打包基本語法
package 包 名
引入包的基本語法
import "包的路徑"
包使用的快速入門
包快速入門-Go 相互調用函數,我們將 func Cal 定義到文件 utils.go , 將 utils.go 放到一個包中,當其它文件需要使用到 utils.go 的方法時,可以 import 該包,就可以使用了.
【為演示:新建項目目錄結構】

utils.go 文件

main.go 文件

包使用的注意事項和細節討論
1)在給一個文件打包時,該包對應一個文件夾,比如這里的 utils 文件夾對應的包名就是 utils,文件的包名通常和文件所在的文件夾名一致,一般為小寫字母。
2)當一個文件要使用其它包函數或變量時,需要先引入對應的包
引入方式 1:import "包名"
引入方式 2:
import (
"包名"
"包名"
)
package 指令在 文件第一行,然后是 import 指令。
在 import 包時,路徑從 $GOPATH 的 src 下開始,不用帶 src , 編譯器會自動從 src 下開始引入
3)為了讓其它包的文件,可以訪問到本包的函數,則該函數名的首字母需要大寫,類似其它語言的 public ,這樣才能跨包訪問。比如 utils.go 的

4)在訪問其它包函數,變量時,其語法是 包名.函數名, 比如這里的 main.go 文件中

5)如果包名較長,Go 支持給包取別名, 注意細節:取別名后,原來的包名就不能使用了

說明: 如果給包取了別名,則需要使用別名來訪問該包的函數和變量。
6)在同一包下,不能有相同的函數名(也不能有相同的全局變量名),否則報重復定義
7)如果你要編譯成一個可執行程序文件,就需要將這個包聲明為 main , 即 package main .這個就是一個語法規范,如果你是寫一個庫 ,包名可以自定義

函數的調用機制
通俗易懂的方式的理解

函數-調用過程
介紹:為了讓大家更好的理解函數調用過程, 看兩個案例,並畫出示意圖,這個很重要
1)傳入一個數+1
對上圖說明
(1)在調用一個函數時,會給該函數分配一個新的空間,編譯器會通過自身的處理讓這個新的空間和其它的棧的空間區分開來
(2)在每個函數對應的棧中,數據空間是獨立的,不會混淆
(3)當一個函數調用完畢(執行完畢)后,程序會銷毀這個函數對應的棧空間。
2)計算兩個數,並返回

return 語句
基本語法和說明

案例演示 1
請編寫要給函數,可以計算兩個數的和和差,並返回結果。

案例演示 2
一個細節說明: 希望忽略某個返回值,則使用 _ 符號表示占位忽略

函數使用的注意事項和細節討論
1)函數的形參列表可以是多個,返回值列表也可以是多個。
2)形參列表和返回值列表的數據類型可以是值類型和引用類型。
3)函數的命名遵循標識符命名規范,首字母不能是數字,首字母大寫該函數可以被本包文件和其它包文件使用,類似 public , 首字母小寫,只能被本包文件使用,其它包文件不能使用,類似 privat
4)函數中的變量是局部的,函數外不生效【案例說明】

5)基本數據類型和數組默認都是值傳遞的,即進行值拷貝。在函數內修改,不會影響到原來的值。

6)如果希望函數內的變量能修改函數外的變量(指的是默認以值傳遞的方式的數據類型),可以傳入變量的地址&,函數內以指針的方式操作變量。從效果上看類似引用 。

7)Go 函數不支持函數重載

8)在 Go 中,函數也是一種數據類型,可以賦值給一個變量,則該變量就是一個函數類型的變量了。通過該變量可以對函數調用

9)函數既然是一種數據類型,因此在 Go 中,函數可以作為形參,並且調用

10)為了簡化數據類型定義,Go 支持自定義數據類型
基本語法:type 自定義數據類型名 數據類型 // 理解: 相當於一個別名案例:type myInt int // 這時 myInt 就等價 int 來使用了.int
案例:type mySum func (int, int) int // 這時 mySum 就等價 一個 函數類型 func (int, int)
舉例說明自定義數據類型的使用:

11)支持對函數返回值命名

12)使用 _ 標識符,忽略返回值

13)Go 支持可變參數

(3) 如果一個函數的形參列表中有可變參數,則可變參數需要放在形參列表最后。代碼演示:

函數的課堂練習
題 1

題 2

題 3:請編寫一個函數 swap(n1 *int, n2 *int) 可以交換 n1 和 n2 的值

函數參數傳遞方式
基本介紹
我們在講解函數注意事項和使用細節時,已經講過值類型和引用類型了,這里我們再系統總結一下,因為這是重難點,值類型參數默認就是值傳遞,而引用類型參數默認就是引用傳遞。
兩種傳遞方式
1)值傳遞
2)引用傳遞
其實,不管是值傳遞還是引用傳遞,傳遞給函數的都是變量的副本,不同的是,值傳遞的是值的拷貝,引用傳遞的是地址的拷貝,一般來說,地址拷貝效率高,因為數據量小,而值拷貝決定拷貝的數據大小,數據越大,效率越低。
值類型和引用類型
1)值類型:基本數據類型 int 系列, float 系列, bool, string 、數組和結構體 struct
2)引用類型:指針、slice 切片、map、管道 chan、interface 等都是引用類型
值傳遞和引用傳遞使用特點

3) 如果希望函數內的變量能修改函數外的變量,可以傳入變量的地址&,函數內以指針的方式操作變量。從效果上看類似引用 。這個案例在前面詳解函數使用注意事項的
變量的作用域
1)函數內部聲明/定義的變量叫局部變量,作用域僅限於函數內部

2)函數外部聲明/定義的變量叫全局變量,作用域在整個包都有效,如果其首字母為大寫,則作用域在整個程序有效

3)如果變量是在一個代碼塊,比如 for / if 中,那么這個變量的的作用域就在該代碼塊

變量作用域的課堂練習
輸出的結果是: tom tom jack tom

函數課堂練習(綜合)
1)函數可以沒有返回值案例,編寫一個函數,從終端輸入一個整數打印出對應的金子塔
分析思路:就是將原來寫的打印金字塔的案例,使用函數的方式封裝,在需要打印時,直接調用即可。

2)編寫一個函數,從終端輸入一個整數(1—9),打印出對應的乘法表
分析思路:就是將原來寫的調用九九乘法表的案例,使用函數的方式封裝,在需要打印時,直接調用即可
代碼:

3)編寫函數,對給定的一個二維數組(3×3)轉置,這個題講數組的時候再完成

