Почему я могу вводить функции псевдонимов и использовать их без приведения?
в Go, если вы определяете новый тип, например:
type MyInt int
вы не можете тогда передать MyInt
к функции, ожидающей int, или наоборот:
func test(i MyInt) {
//do something with i
}
func main() {
anInt := 0
test(anInt) //doesn't work, int is not of type MyInt
}
хорошо. Но почему же тогда то же самое не относится к функциям? например:
type MyFunc func(i int)
func (m MyFunc) Run(i int) {
m(i)
}
func run(f MyFunc, i int) {
f.Run(i)
}
func main() {
var newfunc func(int) //explicit declaration
newfunc = func(i int) {
fmt.Println(i)
}
run(newfunc, 10) //works just fine, even though types seem to differ
}
теперь я не жалуюсь, потому что это избавляет меня от необходимости явно бросать newfunc
типа MyFunc
, как я должен был бы сделать в первом примере; это просто кажется непоследовательным. Я уверен, что для этого есть веская причина; может кто-нибудь просветит меня?
причина, по которой я спрашиваю, в основном потому, что я хотел бы сократить некоторые из моих довольно длинных типов функций таким образом, но я хочу убедиться, что это ожидаемо и приемлемо для этого:)
2 ответа:
оказывается, это недоразумение, которое у меня было о том, как идут дела с типами, которые можно решить, прочитав соответствующую часть спецификации:
http://golang.org/ref/spec#Type_identity
соответствующее различие, о котором я не знал, было то, что имени и безымянный типы.
по имени типы-это типы с именем, такие как int, int64, float, string, bool. Кроме того, любой тип вы создаете с помощью " тип " является именованным типом.
безымянный типы-это такие как [] string, map [string]string, [4]int. У них нет названия, просто описание, соответствующее тому, как они должны быть структурированы.
Если вы сравниваете два именованных типа, имена должны совпадать, чтобы они были взаимозаменяемыми. Если вы сравниваете именованный и безымянный тип, то пока базовое представление матчей, вы хорошо иди!
например, учитывая следующие типы:
type MyInt int type MyMap map[int]int type MySlice []int type MyFunc func(int)
следующее недопустимо:
var i int = 2 var i2 MyInt = 4 i = i2 //both named (int and MyInt) and names don't match, so invalid
в следующем порядке:
is := make([]int) m := make(map[int]int) f := func(i int){} //OK: comparing named and unnamed type, and underlying representation //is the same: func doSlice(input MySlice){...} doSlice(is) func doMap(input MyMap){...} doMap(m) func doFunc(input MyFunc){...} doFunc(f)
Я немного потрошил я не знал, что раньше, так что я надеюсь, что проясняет тип жаворонок немного для кого-то другого! А значит гораздо меньше кастинга, чем я сначала думал:)
и вопрос, и ответ довольно поучительны. Однако я хотел бы поднять различие, которое не ясно в ответе литна.
Именем Типа отличается от Неназываемого Типа.
переменная Именем Типа присваивается переменной Неназываемого Типа, наоборот.
переменная разных Именем Типа не присваиваем друг другу.
http://play.golang.org/p/uaYHEnofT9
import ( "fmt" "reflect" ) type T1 []string type T2 []string func main() { foo0 := []string{} foo1 := T1{} foo2 := T2{} fmt.Println(reflect.TypeOf(foo0)) fmt.Println(reflect.TypeOf(foo1)) fmt.Println(reflect.TypeOf(foo2)) // Output: // []string // main.T1 // main.T2 // foo0 can be assigned to foo1, vice versa foo1 = foo0 foo0 = foo1 // foo2 cannot be assigned to foo1 // prog.go:28: cannot use foo2 (type T2) as type T1 in assignment // foo1 = foo2 }