GOベース:機能、閉鎖、再帰

ディレクトリ

機能

GO機能の特徴:

関数の宣言を移動します:

GO関数パラメータ

GO関数の戻り値

無名関数

クロージャ

ゴー閉鎖

再帰関数

フィボナッチ数(フィボナッチ)


機能

GO機能の特徴:

  • プロトタイプを宣言する必要はありません。
  • 不確実な変数のパラメータをサポートしています
  • 戻り値の型は、最終的な表面に複数の戻り値のサポートを書き込みます
  • 名前付きリターン・パラメータをサポートしています。 
  • 匿名関数とクロージャをサポートしています
  • 関数は、関数が変数に割り当てることができ、タイプです
  • ネストされた(ネストされた)パッケージをサポートしていません同じ機能の二つの名前を持つことはできません。
  • オーバーロードされた(過負荷)をサポートしていません 
  • これは、デフォルトパラメータ(デフォルトパラメータ)、オプションのパラメータをサポートしていません。
  • パラメータが通過する:それは値渡しまたは参照によって渡されているかどうか、関数に渡されたコピーは、しかし、値が値のコピーである渡され、可変です。これは、送信された基準アドレスのコピーです。
  • キーワードFUNC定義関数を使用して、開口部のブレースはまだ新しい行を開始することはできません

関数の宣言を移動します:

package main

import "fmt"

func test(fn func() int) int {
    return fn()
}
// 定义函数类型。
type FormatFunc func(s string, x, y int) string 

func format(fn FormatFunc, s string, x, y int) string {
    return fn(s, x, y)
}

func main() {
    s1 := test(func() int { return 100 }) // 直接将匿名函数当参数。

    s2 := format(func(s string, x, y int) string {
        return fmt.Sprintf(s, x, y)
    }, "%d, %d", 10, 20)

    println(s1, s2)
}

//  返回结果
//  100 10, 20

GO関数パラメータ

関数は、2つの方法でパラメータを渡すことがあります。

  • 値が渡されます:機能で変更のパラメータは、実際のパラメータには影響しませんので、場合関数に渡された関数のコピーを呼び出して実際のパラメータを指します。
  • 参照で渡さ:関数呼び出しは、関数の実パラメータのアドレスを通過するときを意味し、その後に行わパラメータを変更するには、それが機能で実際のパラメータに影響を与えます。
  • デフォルトでは、囲碁言語は値によって渡され、それは、通話中に実際のパラメータには影響しません。

注1:かどうかを値渡しまたは参照によって渡され、関数に渡されたコピーは、変数が、しかし、渡された値が値のコピーです。参照渡し、コピーアドレスで一般的な、より効率的なコピーアドレスに。コピーをコピーした値は、パフォーマンスを下げ、より大きな目標、対象物の大きさに依存します。

注2:参照マップ、スライス、ちゃん、ポインタ、インターフェイスデフォルトの配信。

可変パラメータの任意のタイプ:固定されていないパラメータの種類と各パラメータの関数です。

送信データインターフェースの任意のタイプで{}慣用移動での使用、及びタイプのインタフェース{}安全です。

func myfunc(args ...interface{}) {
  }

あなたがスライスオブジェクトが変更パラメータを行う使用すると、拡大しなければなりません。(slice...)

package main

import (
    "fmt"
)

func test(s string, n ...int) string {
    var x int
    for _, i := range n {
        x += i
    }

    return fmt.Sprintf(s, x)
}

func main() {
    s := []int{1, 2, 3}
    res := test("sum: %d", s...)    // slice... 展开slice
    println(res)
}

GO関数の戻り値

  • "_"識別子は、関数の戻り値を無視します
  • 囲碁の戻り値は、指定された、とあなたは、関数本体の先頭で変数宣言の場合と同様のものとすることができます
  • 名前の戻り値は、文書として使用することができ、特定の意味を持っている必要があります。

無名関数

匿名関数は、関数名の実装を定義する必要はありません機能をいいます。

そこに行き、同じ機能をコードで定義された任意の時点匿名関数で通常の変数や使用、ゴー言語サポートとして渡すことができます。

匿名関数は、関数宣言、関数名なしの機能体組成物から成ります。関数内で直接変数を使用することができ優位無名関数は、宣言する必要はありません。

package main

import (
    "fmt"
    "math"
)

func main() {
    getSqrt := func(a float64) float64 {
        return math.Sqrt(a)
    }
    fmt.Println(getSqrt(4))
}

// 返回
// 2

変数の初期化変数の初期化のgetSqrtと少し異なる前に指定された変数は、FUNCを使用する最初の定義の上方に、funcは関数の定義であるが、この機能と最大差の関数ではない関数名、上にあること、無名関数。ここでは変数として動作する機能として。

Golang匿名関数は、構造体のフィールドと、変数に割り当てられた、またはチャネルで送信することができます。

package main

func main() {
    // --- function variable ---
    fn := func() { println("Hello, World!") }
    fn()

    // --- function collection ---
    fns := [](func(x int) int){
        func(x int) int { return x + 1 },
        func(x int) int { return x + 2 },
    }
    println(fns[0](100))

    // --- function as field ---
    d := struct {
        fn func() string
    }{
        fn: func() string { return "Hello, World!" },
    }
    println(d.fn())

    // --- channel of function ---
    fc := make(chan func() string, 2)
    fc <- func() string { return "Hello, World!" }
    println((<-fc)())
}

出力:

    Hello, World!
    101
    Hello, World!
    Hello, World!

クロージャ

(:すなわち、物理的環境の閉鎖の組み合わせは、その関連する機能によって参照される閉鎖機能+ =基準環境)。

関数とクロージャ

ゴー閉鎖

package main

import (
	"fmt"
)

func a() func() int {
	i := 0
	b := func() int {
		i++
		fmt.Println(i)
		return i
	}
	return b
}

func main() {
	c := a()
	c()
	c()
	c()

	fmt.Println("a() //不会输出i")
	a() //不会输出i

	c2 := a()
	c2()
	c2()
	c2()

	//输出结果
	//1
	//2
	//3
	//a() //不会输出i
	//1
	//2
	//3
}

 

このコードは2つの特徴があります。

ネストされた関数B iの値の関数は、関数の内部機能Bを返した後に実行するvar cを完了ディスプレイ=()、変数cは関数bに実際点にある()、及び、関数cを(実行)、第1、第2、第3など。実際には、コードはクロージャを作成します。言うことである()内の変数cの参照機能(機能B)外部関数()、理由:

当函数a()的内部函数b()被函数a()外的一个变量引用的时候,就创建了一个闭包。 在上面的例子中,由于闭包的存在使得函数a()返回后,a中的i始终存在,这样每次执行c(),i都是自加1后的值。 从上面可以看出闭包的作用就是在a()执行完并返回后,闭包使得go的垃圾回收机制GC不会收回a()所占用的资源,因为a()的内部函数b()的执行需要依赖a()中的变量i。

在给定函数被多次调用的过程中,这些私有变量能够保持其持久性。变量的作用域仅限于包含它们的函数,因此无法从其它程序代码部分进行访问。不过,变量的生存期是可以很长,在一次函数调用期间所创建所生成的值在下次函数调用时仍然存在。正因为这一特点,闭包可以用来完成信息隐藏,并进而应用于需要状态表达的某些编程范型中

下面来想象另一种情况,如果a()返回的不是函数b(),情况就完全不同了。因为a()执行完后,b()没有被返回给a()的外界,只是被a()所引用,而此时a()也只会被b()引 用,因此函数a()和b()互相引用但又不被外界打扰(被外界引用),函数a和b就会被GC回收。所以直接调用a();是页面并没有信息输出。

下面来说闭包的另一要素引用环境。c()跟c2()引用的是不同的环境,在调用i++时修改的不是同一个i,因此两次的输出都是1。函数a()每进入一次,就形成了一个新的环境,对应的闭包中,函数都是同一个函数,环境却是引用不同的环境。这和c()和c()的调用顺序都是无关的。

递归函数

递归,就是在运行的过程中调用自己。 一个函数调用自己,就叫做递归函数。

构成递归需具备的条件:

    1.子问题须与原始问题为同样的事,且更为简单。
    2.不能无限制地调用本身,须有个出口,化简为非递归状况处理。

斐波那契数列(Fibonacci)

这个数列从第3项开始,每一项都等于前两项之和。

package main

import "fmt"

func fibonaci(i int) int {
    if i == 0 {
        return 0
    }
    if i == 1 {
        return 1
    }
    return fibonaci(i-1) + fibonaci(i-2)
}

func main() {
    var i int
    for i = 0; i < 10; i++ {
        fmt.Printf("%d\n", fibonaci(i))
    }
}

输出结果:

    0
    1
    1
    2
    3
    5
    8
    13
    21
    34

 

 

 

发布了412 篇原创文章 · 获赞 1349 · 访问量 217万+

おすすめ

転載: blog.csdn.net/fly910905/article/details/104460565