Ответ 1
Обратите внимание, что существует различие между равенством и идентичностью. Операторы ==
и !=
в Go1 сравнивают значения для эквивалентности (за исключением сравнения каналов), а не для идентичности. Поскольку эти операторы пытаются не смешивать равенство и идентичность, Go1 является более последовательным, чем pre-Go1 в этом отношении.
Функциональное равенство отличается от тождества функции.
Одной из причин невозможности использования типов функций ==
и !=
является производительность. Например, следующее закрытие не использует какие-либо переменные из его среды:
f := func(){fmt.Println("foo")}
Отказ от сравнения функций позволяет компилятору генерировать единую реализацию для закрытия, вместо того чтобы требовать времени выполнения для создания нового закрытия (во время выполнения). Таким образом, с точки зрения производительности решение о запрете сравнения функций было хорошим решением.
В отношении использования пакета reflect
для определения идентичности функции такой код, как
func SomeFun() {}
func AnotherFun() {}
func main() {
sf1 := reflect.ValueOf(SomeFun)
sf2 := reflect.ValueOf(SomeFun)
fmt.Println(sf1.Pointer() == sf2.Pointer()) // Prints true
af1 := reflect.ValueOf(AnotherFun)
fmt.Println(sf1.Pointer() == af1.Pointer()) // Prints false
}
зависит от поведения undefined. Нет никаких гарантий относительно того, что программа будет печатать. Компилятор может решить, что он объединит SomeFun
и AnotherFun
в одну реализацию, и в этом случае второй оператор печати напечатает true
. На самом деле нет абсолютно никакой гарантии, что первый оператор печати напечатает true
(он может, в рамках какого-либо другого компилятора Go1 и времени выполнения, напечатать false
).
Правильный ответ на ваш первоначальный вопрос:
package main
import "fmt"
func F1() {}
func F2() {}
var F1_ID = F1 // Create a *unique* variable for F1
var F2_ID = F2 // Create a *unique* variable for F2
func main() {
f1 := &F1_ID // Take the address of F1_ID
f2 := &F2_ID // Take the address of F2_ID
// Compare pointers
fmt.Println(f1 == f1) // Prints true
fmt.Println(f1 == f2) // Prints false
}