W Go, jeśli zdefiniujesz nowy typ, np .:
type MyInt int
Nie możesz wtedy przekazać a MyInt
do funkcji oczekującej int lub odwrotnie:
func test(i MyInt) {
//do something with i
}
func main() {
anInt := 0
test(anInt) //doesn't work, int is not of type MyInt
}
W porządku. Ale dlaczego w takim razie to samo nie dotyczy funkcji? na przykład:
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
}
Teraz nie narzekam, ponieważ oszczędza mi to konieczności jawnego rzutowania newfunc
na typ MyFunc
, tak jak musiałbym to zrobić w pierwszym przykładzie; po prostu wydaje się niespójne. Jestem pewien, że jest ku temu dobry powód; czy ktoś może mnie oświecić?
Pytam głównie dlatego, że chciałbym w ten sposób skrócić niektóre z moich dość długich typów funkcji, ale chcę się upewnić, że jest to oczekiwane i dopuszczalne :)
type
jest bardziej przydatny w Go niż w Scali. Niestety, Scala ma tylko aliasy typów.Odpowiedzi:
Okazuje się, że jest to nieporozumienie, które miałem na temat tego, jak Go radzi sobie z typami, które można rozwiązać, czytając odpowiednią część specyfikacji:
http://golang.org/ref/spec#Type_identity
Istotne rozróżnienie, którego nie byłem świadomy, dotyczyło typów nazwanych i nienazwanych .
Nazwane typy to typy z nazwą, na przykład int, int64, float, string, bool. Ponadto każdy typ utworzony za pomocą „typu” jest nazwanym typem.
Typy nienazwane to takie, jak [] string, map [string] string, [4] int. Nie mają nazwy, a jedynie opis odpowiadający ich strukturze.
Jeśli porównujesz dwa nazwane typy, nazwy muszą być zgodne, aby można było je stosować zamiennie. Jeśli porównasz nazwany i nienazwany typ, to tak długo, jak pasuje reprezentacja bazowa , możesz działać!
np. biorąc pod uwagę następujące typy:
następujące informacje są nieprawidłowe:
co jest w porządku:
Jestem trochę wypatroszony, że nie wiedziałem tego wcześniej, więc mam nadzieję, że to trochę wyjaśnia ten typ dla kogoś innego! A to oznacza znacznie mniej castingów, niż myślałem na początku :)
źródło
is := make(MySlice, 0); m := make(MyMap)
, który jest bardziej czytelny w niektórych kontekstach.Zarówno pytanie, jak i odpowiedź są dość pouczające. Chciałbym jednak przywołać rozróżnienie, które nie jest jasne w odpowiedzi Lytnusa.
Typ nazwany różni się od Typu bez nazwy .
Zmienną typu nazwanego można przypisać do zmiennej typu nienazwanego i odwrotnie.
Zmiennych o różnych nazwanych typach nie można przypisywać sobie nawzajem.
http://play.golang.org/p/uaYHEnofT9
źródło