Можно ли передавать функции в качестве параметров?
В Java я могу сделать что-то вроде
derp(new Runnable { public void run () { /* run this sometime later */ } })
и "запустить" код в методе позже. Это трудная задача (анонимный внутренний класс), но это можно сделать.
Есть ли в Go что-то, что может облегчить передачу функции/обратного вызова в качестве параметра?
Ответы
Ответ 1
Да, рассмотрим некоторые из этих примеров:
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 "" })
}
Играть: http://play.golang.org/p/XNMtrDUDS0
Тур: https://tour.golang.org/moretypes/25 (Закрытие функций)
Ответ 2
Вы можете передать функцию как параметр функции Go. Ниже приведен пример передачи функции в качестве параметра другой функции Go:
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)
}
Вы можете попробовать это: https://play.golang.org/p/9mAOUWGp0k
Ответ 3
Вот пример реализации "Карта" в Go. Надеюсь, это поможет!
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)
}
Ответ 4
Вот простой пример:
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))
}
Ответ 5
Надеюсь, приведенный ниже пример обеспечит большую ясность.
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
}})
}
Ответ 6
Да Go принимает первоклассные функции.
См. статью "Функции первого класса в Go" для полезных ссылок.