Bu derleme zamanı hatası, somut bir türü bir arabirim türüne atamaya veya geçirmeye (veya dönüştürmeye) çalıştığınızda ortaya çıkar ; ve türün kendisi arabirimi uygulamaz, yalnızca türe bir gösterici .
Bir örnek görelim:
type Stringer interface {
String() string
}
type MyType struct {
value string
}
func (m *MyType) String() string { return m.value }
Stringer
Arayüz tipi bir yöntem, yalnızca var String()
. Bir arayüz değerinde saklanan herhangi bir değer Stringer
bu yönteme sahip olmalıdır. Ayrıca a oluşturduk MyType
ve işaretçi alıcısı MyType.String()
ile bir yöntem oluşturduk . Bu, yöntemin türün yöntem kümesinde olduğu , ancak türünde olmadığı anlamına gelir .String()
*MyType
MyType
Bir MyType
tür değişkenine bir değer atamaya çalıştığımızda Stringer
, söz konusu hatayı alırız:
m := MyType{value: "something"}
var s Stringer
s = m
Biz türünde bir değer atamak deneyin eğer herşey yolunda *MyType
için Stringer
:
s = &m
fmt.Println(s)
Ve beklenen sonucu elde ederiz ( Go Playground'da deneyin ):
something
Bu derleme zamanı hatasını almak için gerekenler:
- Atanan (veya geçirilen veya dönüştürülen) işaretçi olmayan somut türden bir değer
- Atanan (veya iletilen veya dönüştürülen) bir arabirim türü
- Somut tip, arayüzün gerekli yöntemine sahiptir, ancak bir işaretçi alıcısı ile
Sorunu çözme olasılıkları:
- Değere yönelik bir işaretçi kullanılmalıdır, bu işaretçi, yöntem kümesi, işaretçi alıcı ile yöntemi içerecektir.
- Veya alıcı türü işaretçi olmayan olarak değiştirilmelidir , bu nedenle işaretçi olmayan somut türün yöntem kümesi de yöntemi içerecektir (ve böylece arayüzü karşılayacaktır). Yöntemin değeri değiştirmesi gerekiyorsa, işaretçi olmayan bir alıcı bir seçenek değildir, bu uygulanabilir veya olmayabilir.
Yapılar ve gömme
Kullanırken yapılar ve katıştırma , genellikle "siz" bir arabirim uygulamak (a yöntem uygulanmasını sağlamak) değil, ama bir tür aşağıdaki konularda gömülecek struct
. Bu örnekteki gibi:
type MyType2 struct {
MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: m}
var s Stringer
s = m2
Yine, derleme zamanı hatası, çünkü yöntem kümesi gömülü yöntemin yöntemini MyType2
içermez , yalnızca yöntem kümesini içerir , bu nedenle aşağıdakiler çalışır ( Go Playground'da deneyin ):String()
MyType
*MyType2
var s Stringer
s = &m2
*MyType
Yalnızca işaretçi olmayan bir işaretçi yerleştirirsek ve kullanırsak MyType2
( Go Playground'da deneyin) çalışmasını da sağlayabiliriz :
type MyType2 struct {
*MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: &m}
var s Stringer
s = m2
Ayrıca, ne yerleştirirsek (ya MyType
da *MyType
), bir işaretçi kullanırsak *MyType2
, her zaman işe yarar ( Go Playground'da deneyin ):
type MyType2 struct {
*MyType
}
m := MyType{value: "something"}
m2 := MyType2{MyType: &m}
var s Stringer
s = &m2
Spesifikasyondaki ilgili bölüm ( Yapı türleri bölümünden ):
Bir yapı türü S
ve adı verilen bir tür verildiğinde T
, yükseltilen yöntemler yapının yöntem kümesine aşağıdaki gibi dahil edilir:
- Eğer
S
anonim alan içeren T
, yöntem setleri S
ve *S
her iki alıcılı yöntemleri terfi içerir T
. Yöntem seti, *S
aynı zamanda, alıcı ile yükseltilmiş yöntemleri de içerir *T
.
- Eğer
S
anonim alan içeren *T
, yöntem setleri S
ve *S
her iki alıcılı yöntemleri terfi içerir T
veya *T
.
Yani başka bir deyişle: işaretçi olmayan bir türü gömersek, işaretçi olmayan gömücünün yöntem kümesi yalnızca işaretçi olmayan alıcılara sahip yöntemleri alır (gömülü türden).
Bir işaretçi türü gömersek, işaretçi olmayan gömücünün yöntem kümesi, hem işaretçi hem de işaretçi olmayan alıcılarla (gömülü türden) yöntemler alır.
Gömülü tipin işaretçi olup olmadığına bakılmaksızın, gömücü için bir işaretçi değeri kullanırsak, gömülü tipin işaretçi seti metodu her zaman hem işaretçi hem de işaretçi olmayan alıcılarla (gömülü tipten) yöntemleri alır.
Not:
Çok benzer bir durum var, yani bir değerini saran bir arabirim değeriniz olduğunda ve ondan başka bir arabirim değeri atamayaMyType
çalıştığınızda ,. Bu durumda, iddia yukarıda açıklanan nedenlerden dolayı geçerli olmayacaktır, ancak biraz farklı bir çalışma zamanı hatası alıyoruz:Stringer
m := MyType{value: "something"}
var i interface{} = m
fmt.Println(i.(Stringer))
Çalışma zamanı paniği ( Go Playground'da deneyin ):
panic: interface conversion: main.MyType is not main.Stringer:
missing method String
Tip assert yerine dönüştürmeye çalışırken, bahsettiğimiz derleme zamanı hatasını alıyoruz:
m := MyType{value: "something"}
fmt.Println(Stringer(m))
func (m *MyType)
" veya hiçbiri . Öyle mi? Farklı "üye işlevleri" türlerini karıştırabilir miyim, örneğinfunc (m *MyType)
&func (m MyType)
?