Bisakah fungsi dilewatkan sebagai parameter?

158

Di Jawa saya bisa melakukan sesuatu seperti

derp(new Runnable { public void run () { /* run this sometime later */ } })

dan "jalankan" kode dalam metode nanti. Ini adalah rasa sakit untuk ditangani (kelas batin anonim), tetapi bisa dilakukan.

Apakah Go memiliki sesuatu yang dapat memfasilitasi fungsi / panggilan balik yang dilewatkan sebagai parameter?

Saad
sumber
7
Nit / klarifikasi untuk pembaca: Di Jawa, "fungsi" tidak dapat dilewati (sebenarnya, semua "fungsi" di Jawa lebih tepat disebut Metode). Runnable (dan kelas dalam anonim yang berasal dari itu) hanya itu: tipe dari objek yang dipakai yang berlangganan antarmuka yang diperlukan ..
2
(Enam tahun kemudian ...) Java sekarang memiliki cara untuk lulus metode (misalnya containingObject::instanceMethodName): docs.oracle.com/javase/tutorial/java/javaOO/…
vazor

Jawaban:

226

Ya, perhatikan beberapa contoh ini:

package main

import "fmt"

// convert types take an int and return a string value.
type convert func(int) string

// value implements convert, returning x as string.
func value(x int) string {
    return fmt.Sprintf("%v", x)
}

// quote123 passes 123 to convert func and returns quoted string.
func quote123(fn convert) string {
    return fmt.Sprintf("%q", fn(123))
}

func main() {
    var result string

    result = value(123)
    fmt.Println(result)
    // Output: 123

    result = quote123(value)
    fmt.Println(result)
    // Output: "123"

    result = quote123(func(x int) string { return fmt.Sprintf("%b", x) })
    fmt.Println(result)
    // Output: "1111011"

    foo := func(x int) string { return "foo" }
    result = quote123(foo)
    fmt.Println(result)
    // Output: "foo"

    _ = convert(foo) // confirm foo satisfies convert at runtime

    // fails due to argument type
    // _ = convert(func(x float64) string { return "" })
}

Mainkan: http://play.golang.org/p/XNMtrDUDS0

Tur: https://tour.golang.org/moretypes/25 (Penutupan Fungsi)

dskinner
sumber
Apakah mungkin untuk melewatkan parameter ke fungsi yang juga merupakan parameter? Dalam contoh di atas, hal-hal yang dicetak sulit dikodekan: Mencetak 123. Dapatkah ada perubahan yang dilakukan sehingga kita dapat mencetak sesuatu yang lain daripada 123? Tanpa mendeklarasikan variabel global.
Saty
1
Jika saya memahami pertanyaan Anda dengan benar, saya pikir Anda sedang mencari func yang mengembalikan func, lihat di sini di mana saya mengganti fungsi "quote123" dengan kode "fungsi" hardcode yang mencapai hasil yang sama setelah Anda memberikan beberapa input: play.golang.org/p/52ahWAI2xsG
dskinner
34

Anda bisa meneruskan fungsi sebagai parameter ke fungsi Go. Berikut adalah contoh fungsi lewat sebagai parameter ke fungsi Go lainnya:

package main

import "fmt"

type fn func(int) 

func myfn1(i int) {
    fmt.Printf("\ni is %v", i)
}
func myfn2(i int) {
    fmt.Printf("\ni is %v", i)
}
func test(f fn, val int) {
    f(val)
}
func main() {
    test(myfn1, 123)
    test(myfn2, 321)
}

Anda bisa mencobanya di: https://play.golang.org/p/9mAOUWGp0k

SeattleOrBayArea
sumber
2
Terima kasih! Ini adalah contoh yang sangat jelas tentang bagaimana cara terbaik untuk menggunakan ide ini! Saya telah membuatnya kembali menggunakan tabel pencarian struct yang menyimpan info, termasuk pointer ke fungsi yang ingin Anda jalankan. Sempurna untuk ini!
James O'Toole
15

Berikut ini contoh implementasi "Peta" di Go. Semoga ini membantu!!

func square(num int) int {
    return num * num
}

func mapper(f func(int) int, alist []int) []int {
    var a = make([]int, len(alist), len(alist))
    for index, val := range alist {

        a[index] = f(val)
    }
    return a
}

func main() {
    alist := []int{4, 5, 6, 7}
    result := mapper(square, alist)
    fmt.Println(result)

}
robus gauli
sumber
8

Ini adalah contoh sederhana:

    package main

    import "fmt"

    func plusTwo() (func(v int) (int)) {
        return func(v int) (int) {
            return v+2
        }
    }

    func plusX(x int) (func(v int) (int)) {
       return func(v int) (int) {
           return v+x
       }
    }

    func main() {
        p := plusTwo()
        fmt.Printf("3+2: %d\n", p(3))

        px := plusX(3)
        fmt.Printf("3+3: %d\n", px(3))
    }
foamdino
sumber
4
itu mengembalikan fungsi yang tidak melewati fungsi
John LaBarge
2

Saya harap contoh di bawah ini akan memberikan lebih banyak kejelasan.

package main

type EmployeeManager struct{
    category            string
    city                string
    calculateSalary     func() int64
}


func NewEmployeeManager() (*EmployeeManager,error){

    return &EmployeeManager{
        category : "MANAGEMENT",
        city : "NY",
        calculateSalary: func() int64 {
            var calculatedSalary int64
            // some formula
            return calculatedSalary
        },
    },nil
}

func (self *EmployeeManager) emWithSalaryCalculation(){
    self.calculateSalary = func() int64 {
        var calculatedSalary int64
        // some new formula
        return calculatedSalary
    }
}

func updateEmployeeInfo(em EmployeeManager){
    // Some code
}

func processEmployee(){
    updateEmployeeInfo(struct {
        category        string
        city            string
        calculateSalary func() int64
    }{category: "", city: "", calculateSalary: func() int64 {
        var calculatedSalary int64
        // some new formula
        return calculatedSalary
    }})
}
CodeAdocate
sumber
-2

Ya Go memang menerima fungsi kelas satu.

Lihat artikel "Fungsi Kelas Pertama di Go" untuk tautan yang bermanfaat.

AbdulFattah Popoola
sumber
4
Harap perluas tanggapan ini beberapa; termasuk contoh, tautan ke referensi (misalnya referensi aktual), dll.
3
sebenarnya ada 0 informasi di halaman itu, hanya tautan ke contoh bodoh dengan kode sumber.
OZ_