【GOプログラミング言語】機能

関数



ここに画像の説明を挿入


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
}




おすすめ

転載: blog.csdn.net/guanguan12319/article/details/130587071