Neden takma ad işlevlerini yazıp bunları çevrim yapmadan kullanabilirim?


98

Go'da, yeni bir tür tanımlarsanız, örneğin:

type MyInt int

O zaman a'yı MyIntint bekleyen bir işleve geçiremezsiniz veya tam tersi:

func test(i MyInt) {
    //do something with i
}

func main() {
    anInt := 0
    test(anInt) //doesn't work, int is not of type MyInt
}

İnce. Peki o zaman neden aynı şey işlevler için geçerli değil? Örneğin:

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
}

Benim açıkça döküm zorunda kaydeder çünkü Şimdi, Ben şikayetçi değilim newfunctipine MyFuncİlk örnekte yapmak zorunda kalacak gibi; sadece tutarsız görünüyor. Eminim bunun iyi bir nedeni vardır; kimse beni aydınlatabilir mi?

Sormamın nedeni, esas olarak, oldukça uzun olan bazı fonksiyon türlerimi bu şekilde kısaltmak istemem, ancak bunu yapmanın beklenen ve kabul edilebilir olduğundan emin olmak istiyorum :)


typeGo'da Scala'dan daha kullanışlıdır. Scala'nın yalnızca tür takma adları vardır, ne yazık ki.
Rick-777

4
Go now aslında tür takma adlarına sahip github.com/golang/go/issues/18130
Hut8

birisi ikinci kod parçacığını açıklayabilir mi? Bu işlev bildirimlerini gerçekten alamıyorum
DevX

Yanıtlar:


150

Görünüşe göre bu, Go'nun türlerle nasıl başa çıktığı konusunda sahip olduğum bir yanlış anlama ve bu, spesifikasyonun ilgili bölümünü okuyarak çözülebilir:

http://golang.org/ref/spec#Type_identity

Farkında olmadığım ilgili ayrım, isimlendirilmiş ve isimsiz tiplerdi.

Adlandırılmış türler, int, int64, float, string, bool gibi bir ada sahip türlerdir. Ayrıca, 'tür' kullanarak oluşturduğunuz her tür, adlandırılmış türdür.

Adsız türler [] dize, eşleme [dize] dizgi, [4] int gibi türlerdir. İsimleri yoktur, sadece nasıl yapılandırılacaklarına karşılık gelen bir tanımları vardır.

İki adlandırılmış türü karşılaştırırsanız, birbirlerinin yerine geçebilmeleri için adların eşleşmesi gerekir. Adlı ve adsız bir türü karşılaştırırsanız , temeldeki temsil eşleştiği sürece gitmekte fayda var!

örneğin aşağıdaki türler verilir:

type MyInt int
type MyMap map[int]int
type MySlice []int
type MyFunc func(int)

şu geçersizdir:

var i int = 2
var i2 MyInt = 4
i = i2 //both named (int and MyInt) and names don't match, so invalid

aşağıdaki sorun değil:

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)

Biraz içim kırıldı Bunu daha önce bilmiyordum, bu yüzden umarım bu, başka biri için biraz açıklığa kavuşur! Ve ilk başta düşündüğümden çok daha az oyuncu demek :)


1
is := make(MySlice, 0); m := make(MyMap)Bazı bağlamlarda daha okunaklı olanı da kullanabilirsiniz .
R2B2

13

Hem soru hem de cevap oldukça aydınlatıcı. Bununla birlikte, Lytnus'un cevabında net olmayan bir ayrımı gündeme getirmek istiyorum.

  • Adlandırılmış Tür , Adsız Türden farklıdır .

  • Değişken adlandırılmış Tip değişkenine atanabilir olan adsız Tip , tersi de geçerlidir.

  • Farklı Ad Tipi Değişkeni birbirine atanamaz.

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