Fonksiyonlar parametre olarak iletilebilir mi?


158

Java'da şöyle bir şey yapabilirim

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

ve yöntemdeki kodu daha sonra "çalıştır". Bu, ele alınması gereken bir acıdır (anonim iç sınıf), ancak yapılabilir.

Go'nun bir işlev / geri aramanın parametre olarak iletilmesini kolaylaştırabilecek bir şeyi var mı?


7
Okurlar için nit / açıklama: Java'da "işlevler" pasif değildir (aslında, Java'daki tüm "işlevler" daha uygun bir şekilde Yöntemler olarak adlandırılır). Çalıştırılabilir (ve bundan türeyen anonim iç sınıflar) sadece: gerekli arayüze abone olan nesnelerin örneklendiği bir tür ..

2
(Altı yıl sonra ...) Java'nın artık yöntemleri geçirmenin bir yolu var (örn. containingObject::instanceMethodName): Docs.oracle.com/javase/tutorial/java/javaOO/…
vazor

Yanıtlar:


226

Evet, aşağıdaki örneklerden bazılarını göz önünde bulundurun:

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 "" })
}

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

Tur: https://tour.golang.org/moretypes/25 (İşlev Kapanışları)


Kendisi de parametre olan bir işleve bir parametre iletmek mümkün müdür? Yukarıdaki örneklerde, yazdırılanlar sabit kodlanmıştır: Yazdırma 123. 123 yerine başka bir şey yazdırabilmemiz için herhangi bir değişiklik yapılabilir mi? Global değişkenleri bildirmeden.
Saty

1
Sorunuzu doğru bir şekilde anlarsam, bir fonk döndüren bir fonk arıyorsanız, buraya bir kodlu "quote123" işlevini, bazı girdiyi geçtikten sonra aynı sonucu elde eden "alıntı" işleviyle değiştirdiğime bakın: play.golang.org/p/52ahWAI2xsG
dskinner

34

Bir Go işlevine işlevi parametre olarak iletebilirsiniz. Aşağıda, başka bir Git işlevine parametre olarak işlev aktarma örneği verilmiştir:

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)
}

Bunu şu adreste deneyebilirsiniz: https://play.golang.org/p/9mAOUWGp0k


2
Teşekkür ederim! Bu, bu fikrin en iyi nasıl kullanılacağına dair çok açık bir örnekti! Yürütmek istediğiniz işleve bir işaretçi de dahil olmak üzere bilgi depolayan yapıların bir arama tablosunu kullanarak yeniden yarattık. Bunun için mükemmel!
James O'Toole

15

İşte Go'daki örnek "Harita" uygulaması. Bu yardımcı olur umarım!!

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)

}

8

İşte basit bir örnek:

    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))
    }

4
bir işlevi geçmeyen bir işlevi döndürür
John LaBarge

2

Umarım aşağıdaki örnek daha fazla netlik sağlar.

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
    }})
}

-2

Evet Go birinci sınıf işlevleri kabul eder.

Yararlı bağlantılar için "Devam Eden Birinci Sınıf İşlevler" makalesine bakın .


4
Lütfen bu yanıtı biraz genişletin; bir örnek, referans bağlantısı (örn. gerçek referans) vb. dahil edin.

3
aslında o sayfada 0 bilgi vardır, sadece kaynak kodla aptal örneğe bağlantı.
OZ_
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.