関数
記事ディレクトリ
1. 関数とは何ですか
- 関数は、タスクを実行するコードの基本ブロックです。
- Go 言語には少なくとも 1 つの main() 関数があります。
- 関数を使用してさまざまな関数を分割することができ、論理的に各関数が指定されたタスクを実行します。
- 関数宣言は、関数の名前、戻り値の型、パラメーターをコンパイラーに伝えます。
1. 関数宣言
Go言語の関数定義の形式は以下のとおりです。
func functionName( [parameter list] ) [returnType] {
函数体
}
package main
import "fmt"
/*
-- 函数是基本的代码块,用于执行一个任务
-- Go 语言最少有个 main() 函数
-- 可以通过函数来划分不同功能,逻辑上每个函数执行的是指定的任务
-- 函数声明告诉了编译器函数的名称,返回类型和参数
*/
func main() {
fmt.Println(add(3, 4))
}
// func 函数名 (参数,参数....) 函数调用后的返回值 {
// 函数体 : 执行一段代码
// return 返回结果
//}
func add(a, b int) int {
c := a + b
return c
}
出力
2. 関数の宣言と呼び出し
- パラメータも戻り値も持たない関数
- パラメータが 1 つある関数
- 2 つのパラメータを持つ関数
- 値を返す関数があります
- 複数の戻り値を持つ関数
package main
import "fmt"
func main() {
c := add(3, 4)
fmt.Println(c)
onePrint("guan")
x, y := swap("guan", "hello")
fmt.Println(x, y)
}
// - 无参数无返回值函数
func Println() {
fmt.Println("printinfo")
}
// - 有一个参数的函数
func onePrint(name string) {
fmt.Println("name")
}
// - 有两个参数的函数
// - 有一个返回值的函数
func add(a, b int) int {
c := a + b
return c
}
// - 有多个返回值的函数
func swap(x, y string) (string, string) {
return y, x
}
出力
3. 仮パラメータと実パラメータ
仮パラメータ: 関数を定義する場合、他のポートからの受信データを受信するために使用されるパラメータが仮パラメータです。
実パラメータ: 関数を呼び出すときに、仮パラメータに渡される実際のデータを実パラメータと呼びます。
package main
func main() {
maxNum := max(6, 8)
println(maxNum)
}
// - max 两个数字比大小
// 形式参数:定义函数时,用来接收外埠传入数据的参数,就是形式参数
// 实际参数:调用函数时,传给形参的实际数据叫做实际参数
func max(num1, num2 int) int {
var result int
if num1 > num2 {
result = num1
} else {
result = num2
}
// 一个函数定义上有返回值,那么函数中必须使用return语句
// 返回值
// 调用处需要使用变量接收结果
return result
}
4、可変パラメータ
コンセプト: 関数のパラメータの型は決まっているが、その数が不明な場合は、可変パラメータを使用できます。
func myfunc(arg ... int) {
}
// arg ... int 告诉go这个函数接收不定数量的参数,类型全部是int
package main
import "fmt"
func main() {
getSum(1, 2, 3, 4, 5, 6, 7, 8)
}
// ... 可变参数
func getSum(nums ...int) {
sum := 0
// x.len(),获取元素长度
for i := 0; i < len(nums); i++ {
// x[i] 通过下标取出数据
sum += nums[i]
}
fmt.Println("总和:", sum)
}
出力
5. 値渡しと参照渡し
データストレージの特性によると:
- 値型のデータ: 操作はデータ本体、int、string、bool、float64、array... です。
- 銀川タイプのデータ: 操作はデータ スライス、マップ、チャネルのアドレスです。
値渡し
package main
import "fmt"
func main() {
// 定义一个数组
arr1 := [4]int{
1, 2, 3, 4}
fmt.Println("arr1默认数据", arr1)
update(arr1)
fmt.Println("arr1 调用函数后数据", arr1)
// arr2 的数据是 从arri 复制兴的,所以是不可的空间
// 修改 arr2 并不会影响 arr 1
// 值传递:传递的是数据的副本,修改数据,对于原始约数据没有影响
// 值类型的数据,默认都是值传递:基础炎型、array、struct
}
func update(arr2 [4]int) {
fmt.Println("arr2 接以数据", arr2)
arr2[0] = 10
fmt.Println("arr2 修改后数据", arr2)
}
出力
メモ:
- 関数パラメータが可変パラメータであり、他のパラメータがある場合は、可変パラメータをリストの最後に配置する必要があります。
- 関数のパラメーター リストには、最大 1 つの変数パラメーターを含めることができます。
6. 関数内の変数のスコープ
- スコープ: 変数が使用できる範囲
- ローカル変数: 関数内で定義された変数はローカル変数と呼ばれます。
package main
import "fmt"
func main() {
// 函数体内的局部变量
y := 66
if z := 1; z <= 10 {
// 语句内的局部变量
y := 88
fmt.Println(y) // 局部变量,就近原则
fmt.Println(z)
}
fmt.Println(y)
//fmt.Println(z) // # command-line-arguments
// .\hello.go:15:14: undefined: z
}
func gun01() {
// x 为局部变量
x := 1
println(x)
}
func gun02() {
// fmt.Println(a) //不能在使用在其他函数定义的变量
}
- すべての変数: 関数の外部で定義された変数はグローバル変数と呼ばれます
package main
import "fmt"
// 全局变量
var num int = 99
func main() {
//num := 1
fmt.Println(num)
gun01()
gun02()
}
func gun01() {
//num := 2
println(num)
}
func gun02() {
//num := 3
fmt.Println(num)
}
出力
セブン、延期
defer セマンティクス: 延期、遅延
Go 言語では、関数またはメソッドの実行を遅らせるには defer キーワードを使用します。
package main
import "fmt"
func main() {
num := 1
fmt.Println(num)
defer gun01() // 会被延迟到最后执行
gun02()
}
func gun01() {
num := 2
println(num)
}
func gun02() {
num := 3
fmt.Println(num)
}
出力
defer 関数またはメソッド: 関数またはメソッドの実行が遅延します。
- 関数内に複数の defer ステートメントを追加できます。
当函数执行到最后时,这些defer语句会按照逆序执行,最后该函数返回
特に、リソースを開く操作を実行しているときに、エラーが発生した場合に事前に戻る必要がある場合に、関数に複数の defer ステートメントを追加できます。戻る前に対応するリソースを閉じる必要があります。そうしないと、リソース リークやその他の問題が発生しやすくなります。 - 遅延する呼び出しが多数ある場合、遅延は最終トーク先出し (スタック) モードを採用します。
package main
import "fmt"
func main() {
num := 1
num01 := 6
fmt.Println(num)
defer gun01() // 会被延迟到最后执行
defer gun02()
defer fmt.Println(num01)
}
func gun01() {
num := 2
println(num)
}
func gun02() {
num := 3
fmt.Println(num)
}
出力
import "fmt"
func main() {
num := 1
a := 6
fmt.Println(num)
defer gun01(a) // 在执行a++之前,参数就已经传递进去了,在最后执行
a++
fmt.Println(a)
}
func gun01(x int) {
println(x)
}
出力
8. 機能の性質の探求
package main
import "fmt"
// func() 本身就是一个数据类型
func main() {
// f1 如果不加括号,函数也是一个变量
// f1() 如果加了括号,那就成了函数的调用
fmt.Print("%T\n", f1)
// f1 看着对应函数名对应函数体的地址 0xbbfd60
// f1() 带括号就是将函数直接调用
// 直接定义一个函数类型的变量
fmt.Println()
var x func(int, int)
fmt.Println(x)
// 将格式相同的f1给x进行函数赋值
x = f1
fmt.Println(x) // 和f1地址相同
f1(1, 2)
x(10, 20) //x也是函数类型的,可以直接调用
}
func f1(a, b int) {
fmt.Printf("a:%d,b:%d\n", a, b)
}
函数在 Go 语言中是复合类型,可以看做是一种特殊的变量。
関数名 ( ): 呼び出しの戻り結果
関数名: 関数本体を指すメモリ アドレス、特殊なタイプのポインタ変数
9. 匿名関数
package main
import "fmt"
// func() 本身就是一个数据类型
func main() {
f1()
f2 := f1 //函数本身也是一个变量
f2()
// 匿名函数
f3 := func() {
fmt.Println("f3函数")
}
f3()
func() {
fmt.Println("f4函数")
}() // 匿名函数本身可以调用自己
func(a, b int) {
fmt.Println(a, b)
fmt.Println("f5函数")
}(3, 4) // 匿名函数本身可以调用自己
x := func(a, b int) int {
fmt.Println("f6函数")
return a + b
}(3, 4) // 匿名函数本身可以调用自己
fmt.Println(x)
}
func f1() {
fmt.Println("f1函数")
}
Go 言語は関数型プログラミングをサポートしています。
1. 匿名関数を別の関数のパラメータとして使用し、関数をコールバックします。
2. 匿名関数を別の関数の戻り値として使用して、クロージャ構造を形成します。
10. コールバック関数
Go言語のデータ型の特徴によれば、可以将一个函数作为另外一个函数的参数
.
fun1()、fun2()はfun1関数をfun2関数のパラメータとして使用します。
fun2関数:高階関数と呼ばれ、関数をパラメータとして受け取る関数
fun1 関数: 別の関数のパラメータとしてコールバック関数を呼び出します。
package main
import "fmt"
func main() {
r1 := Sum(1, 1)
fmt.Println(r1)
r2 := oper(5, 5, Sum)
fmt.Println(r2)
r3 := oper(10, 5, Sub)
fmt.Println(r3)
r4 := oper(10, 5, func(a int, b int) int {
if b == 0 {
fmt.Println("除数不能为0")
return 0
}
return a / b
})
fmt.Println(r4)
}
// 高阶函数,可以接收一个函数作为参数
func oper(a, b int, f func(int, int) int) int {
r := f(a, b)
return r
}
func Sum(a, b int) int {
return a + b
}
func Sub(a, b int) int {
return a - b
}
出力
イレブン、閉店
-
外層関数の中にヒューマン層関数があり、このヒューマン層関数では外層関数のローカル変数が操作され、外層関数はこのヒューマン層関数に戻って渡されます。内羽数と外尿数の霊的部分変数を総称して閉包構造と呼ぶ
-
ローカル変数のライフサイクルが変更され、通常のローカル変数は関数の調整で作成され、関数の終了とともに破棄されますが、閉じた構造のローカル変数として、内部関数の証明書が引き続き使用されるため、外部関数の計算で外部列の数が破棄されることはありません
package main
import "fmt"
func main() {
r1 := increment()
fmt.Println(r1)
v1 := r1()
fmt.Println(v1)
v2 := r1()
fmt.Println(v2)
fmt.Println(r1())
fmt.Println(r1())
fmt.Println(r1())
r2 := increment()
v3 := r2()
fmt.Println(v3)
fmt.Println(r1())
fmt.Println(r2())
}
func increment() func() int {
// 局部变量i
i := 0
// 定义一个匿名函数,给变量自增并返回
f := func() int {
i++
return i
}
return f
}