2014-10-01 15 views
8

Boş bir arabirime herhangi bir türde nesne atanabilir. Örneğin,Golang boş arabirim {} işlev türünde

func Println(i interface{}) { 
    fmt.Println(i) 
} 

Biz

Println(3) 
Println(1.5) 
Println("Hello") 

tarafından diyebilirsin Ama

func Map(fn func(interface{})) { 
    ...... 
} 

ben bu arayamam ben fonksiyon tipi için aynı şeyi başarmak cann't aşağıdaki işlevi var tür func (int), func (interfac) türünden farklı olduğu için


e {}).

Fakat func (interface {}) tanımladığımda, gerçekten giriş parametrelerinin herhangi bir türünü kastediyorum. Bunu Golang

+0

Bunlar farklı "türler" dir. Bir arabirimi kabul eden bir işlev ve bir int kabul eden bir işlev farklı şeylerdir. –

+0

Evet, türlerin farklı olduğunu biliyorum. Ama herhangi bir tip parametresini kabul etmek için bir fonksiyon tipini tanımlamam mümkün mü? –

cevap

11

'da nasıl başarabilirim İmzalar eşleşmediği için başarısız olur.

Println(3) numaralı telefonu aradığınızda, işlev ilk bağımsız değişken olarak bir tamsayı almıyor. Bunun yerine tamsayı bir interface{} değişkenine (tamsayılar ara yüzle uyumlu olduğu için otomatik bir dönüşüm) girer ve bu değişken işleve iletilir. Bu dönüşüm çağıran tarafta gerçekleşir, bu nedenle işlev çağırma işlemi func(i int) ile eşleşen bir işlevi çağırmaktan farklıdır.

Rasgele tek işlevler kabul eden bir işlev yazmak istiyorsanız, bağımsız değişken olarak bir interface{} değişkenini almak için bildirmeniz ve ardından reflect paketini kullanarak değeri kontrol etmeniz gerekir. reflect paketi, derleme zamanında imzayı bilmediğiniz keyfi işlevleri çağırmanıza da yardımcı olabilir. Örneğin

:

func Map(f, v interface{}) interface{} { 
    fn := reflect.ValueOf(f) 
    fnType := fn.Type() 
    if fnType.Kind() != reflect.Func || fnType.NumIn() != 1 || fnType.NumOut() != 1 { 
     panic("Expected a unary function returning a single value") 
    } 
    res := fn.Call([]reflect.Value{reflect.ValueOf(v)}) 
    return res[0].Interface() 
} 

Bu argüman v ile verilen fonksiyon f çağırmak ve sonucu döndürür. Sağlanan v, f'un ilk bağımsız değişkenine atanabilir, çağrı panik olmadan başarılı olur. Bu örnekle şu deneyebilirsiniz: http://play.golang.org/p/kkBu56JYb8

+1

Harika cevap için teşekkürler. Aslında {} arayüzünü nasıl kullanacağımı ve bunu başarmak için paketi nasıl yansıtacağımı biliyorum. Arayanın {} arayüzü ile sezgisel olmayan bir işlev sağlamasını istemek yeterli değildir. Otomatik dönüşümü int'den arayüze nasıl dönüştürebiliriz? –

+1

@YiqunHu yapamazsınız. – OneOfOne

+1

Bu, jenerik eksikliğinin dilin işlevsel yönlerini sakat bırakmasının tam olarak nedenidir. – jocull