يسمح Go بأشكال مبسّطة لبعض المحدِّدات.
مثلاً، في البرنامج التالي، t1.M1 شكل مبسّط من (*t1).M1، وt2.M2 شكل مبسّط من (&t2).M2. عند وقت التصريف، سيطبّع المصرِّف الشكلين المبسّطين إلى شكلَيهما الكاملين الأصليين.
تطبع الشيفرة التالية 0 و9، لأن التعديل على t1.X ليس له تأثير على نتيجة تقييم *t1 أثناء تقييم (*t1).M1.
package main
type T struct {
X int
}
func (t T) M1() int {
return t.X
}
func (t *T) M2() int {
return t.X
}
func main() {
var t1 = new(T)
var f1 = t1.M1 // <=> (*t1).M1
t1.X = 9
println(f1()) // 0
var t2 T
var f2 = t2.M2 // <=> (&t2).M2
t2.X = 9
println(f2()) // 9
}
في الشيفرة التالية، تعمل الدالة foo بشكل سليم، لكن الدالة bar ستُنتج panic. السبب أن s.M شكل مبسّط من (*s.T).M. عند وقت التصريف، سيطبّع المصرِّف الشكل المبسّط إلى شكله الكامل الأصلي. عند وقت التشغيل، إذا كان s.T مساوياً لـ nil، فإن تقييم *s.T سيسبّب panic. التعديلان على s.T ليس لهما تأثير على نتيجة تقييم *s.T.
package main
type T struct {
X int
}
func (t T) M() int {
return t.X
}
type S struct {
*T
}
func foo() {
var s = S{T: new(T)}
var f = s.M // <=> (*s.T).M
s.T = nil
f()
}
func bar() {
var s S
var f = s.M // panic
s.T = new(T)
f()
}
func main() {
foo()
bar()
}
يرجى ملاحظة أن قيم طرق الواجهات وقيم الطرق المُحصَّلة عبر الانعكاس ستُوسَّع إلى قيم الطرق المُرقّاة بتأخير. مثلاً، في البرنامج التالي، التعديل على s.T.X له تأثير على نتائج إرجاع قيم الطرق المُحصَّلة عبر الانعكاس وعبر الواجهات.
package main
import "reflect"
type T struct {
X int
}
func (t T) M() int {
return t.X
}
type S struct {
*T
}
func main() {
var s = S{T: new(T)}
var f = s.M // <=> (*s.T).M
var g = reflect.ValueOf(&s).Elem().
MethodByName("M").
Interface().(func() int)
var h = interface{M() int}(s).M
s.T.X = 3
println( f() ) // 0
println( g() ) // 3
println( h() ) // 3
}
المصدر: https://github.com/golang/go/issues/47863
لاحظ أنه كان هناك خطأ في مصرِّف Go القياسي الرسمي قبل الإصدار 1.20. المصرِّفات الأقدم تُلغي توجيه بعض طرق الواجهات في وقت التصريف، لكن عمليات إلغاء التوجيه تُنفَّذ إلى حد بعيد أكثر مما ينبغي لتكون صحيحة. مثلاً، يجب أن تطبع الشيفرة التالية 2 2، لكنها تطبع 1 2 إذا صُرِّفت بمصرِّف Go القياسي الرسمي الإصدار 1.19.
package main
type I interface{ M() }
type T struct{
x int
}
func (t T) M() {
println(t.x)
}
func main() {
var t = &T{x: 1}
var i I = t
var f = i.M
defer f() // 2 (صحيح)
// إلغاء توجيه i.M إلى (*t).M في وقت التصريف (خطأ).
defer i.M() // 1 (خطأ)
t.x = 2
}
أُصلح الخطأ في سلسلة أدوات Go 1.20.