Bolehkah Go secara langsung mewakili panggilan fungsi sebagai jenis untuk digunakan sebagai parameter?

Mary-Kate Olsen
Lepaskan: 2024-10-29 03:29:02
asal
860 orang telah melayarinya

Can Go directly represent function calls as a type for use as parameters?

Taip Go untuk Panggilan Fungsi

Apabila menggunakan kata kunci seperti pergi dan tangguh, panggilan fungsi diperlukan sebagai parameter. Walau bagaimanapun, adakah terdapat jenis tertentu yang boleh digunakan dengan cara yang sama, terutamanya untuk mencipta fungsi yang mengharapkan panggilan fungsi (bukan sekadar fungsi itu sendiri) sebagai hujah?

Keterbatasan dan Penyelesaian

Go tidak menyediakan jenis yang membenarkan fungsi ini secara langsung. Sebaliknya, seseorang boleh menggunakan pembolehubah atau nilai jenis fungsi dan memanggilnya kemudian seolah-olah ia adalah fungsi. Contohnya:

<code class="go">func myFunc() {
    fmt.Println("hi")
}

func main() {
    var f func()
    f = myFunc
    f() // This calls the function value stored in f: myFunc in this example
}</code>
Salin selepas log masuk

Untuk mencapai kefungsian yang diingini yang disebut dalam ulasan, bungkus panggilan fungsi dan argumen dalam func() dan gunakan itu. Contohnya:

<code class="go">func launch(f func()) {
    fmt.Println("Before launch")
    go func() {
        defer fmt.Println("After completion")
        f()
    }()
}</code>
Salin selepas log masuk

Penggunaan:

<code class="go">func main() {
    launch(func() {
        fmt.Println("Hello, playground")
    })

    time.Sleep(time.Second)
}</code>
Salin selepas log masuk

Output:

Before launch
Hello, playground
After completion
Salin selepas log masuk

Kaedah ini tidak melibatkan penyelesaian langsung. Jika parameter berubah, buat salinan sebelum memanggil pelancaran() dan gunakan salinan dalam fungsi literal (penutupan).

Meniru Penjimatan Parameter Automatik

Untuk fungsi tertentu taip, cipta fungsi pembantu dengan tandatangan yang sama, mengembalikan fungsi tanpa parameter. Fungsi yang dikembalikan bertindak sebagai penutup, memanggil fungsi asal dengan parameter. Menggunakan fungsi pembantu dengan berkesan menyimpan parameter, meniru tingkah laku penangguhan:

<code class="go">func wrapPrintln(s string) func() {
    return func() {
        fmt.Println(s)
    }
}</code>
Salin selepas log masuk

Penggunaan:

<code class="go">launch(wrapPrintln(s))</code>
Salin selepas log masuk

Menggunakan Refleksi

Refleksi boleh menghapuskan keperluan untuk salinan manual, tetapi pendekatan ini melibatkan menghantar fungsi sebagai parameter dan bukannya memanggilnya. Ia juga lebih perlahan disebabkan oleh pantulan overhed.

<code class="go">func launch(f interface{}, params ...interface{}) {
    fmt.Println("Before launch")
    go func() {
        defer fmt.Println("After completion")
        pv := make([]reflect.Value, len(params))
        for i, v := range params {
            pv[i] = reflect.ValueOf(v)
        }
        reflect.ValueOf(f).Call(pv)
    }()
}</code>
Salin selepas log masuk

Contoh penggunaan:

<code class="go">func main() {
    i, s := 1, "Hello, playground"

    launch(fmt.Printf, "%d %q\n", i, s)
    i, s = 2, "changed"

    time.Sleep(time.Second)
}</code>
Salin selepas log masuk

Output:

Before launch
1 "Hello, playground"
After completion
Salin selepas log masuk

Pengecualian: Nilai Kaedah

Satu pengecualian di mana penjimatan parameter automatik boleh digunakan adalah dengan nilai kaedah. Apabila x mempunyai jenis statik T dan set kaedah T mengandungi kaedah M, x.M (tanpa memanggilnya) mewakili nilai kaedah yang menangkap salinan x sebagai penerima apabila hasil ungkapan (nilai fungsi) dipanggil.

Atas ialah kandungan terperinci Bolehkah Go secara langsung mewakili panggilan fungsi sebagai jenis untuk digunakan sebagai parameter?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan