گیرنده و رابط

متدهایی که دارای گیرنده‌های مقدار هستند، می‌توانند با استفاده از هر دو مقدار و اشاره‌گرها فراخوانی شوند.

متدهایی که دارای گیرنده‌های اشاره‌گر هستند، تنها می‌توانند با استفاده از اشاره‌گر یا مقادیر قابل آدرس‌دهی فراخوانی شوند.

به عنوان مثال:

type S struct {
  data string
}

func (s S) Read() string {
  return s.data
}

func (s *S) Write(str string) {
  s.data = str
}

sVals := map[int]S{1: {"A"}}

// تنها می‌توانید از یک مقدار برای فراخوانی Read استفاده کنید
sVals[1].Read()

// این قطعاً compile نمی‌شود:
// sVals[1].Write("test")

sPtrs := map[int]*S{1: {"A"}}

// هر دو متد Read و Write می‌توانند با استفاده از یک اشاره‌گر فراخوانی شوند
sPtrs[1].Read()
sPtrs[1].Write("test")

به همین ترتیب، حتی اگر یک متد دارای گیرنده مقدار باشد، می‌تواند یک رابط را با استفاده از گیرنده اشاره‌گر رضایت بخش باشد.

type F interface {
  f()
}

type S1 struct{}

func (s S1) f() {}

type S2 struct{}

func (s *S2) f() {}

s1Val := S1{}
s1Ptr := &S1{}
s2Val := S2{}
s2Ptr := &S2{}

var i F
i = s1Val
i = s1Ptr
i = s2Ptr

// کد زیر compile نخواهد شد زیرا s2Val یک مقدار است و متد f از S2 دارای گیرنده مقدار نیست
// i = s2Val

گوگولنگ مفاهیم عالی در مورد اشاره‌گرها در مقابل مقادیر را در Effective Go شرح داده است.

یادداشت‌های اضافی:

  • یک نوع می‌تواند مجموعه متدهای دارای گیرنده‌های مقدار و مجموعه متدهای دارای گیرنده‌های اشاره‌گر را داشته باشد
    • مجموعه متدهای دارای گیرنده‌های مقدار زیرمجموعه‌ای از مجموعه متدهای دارای گیرنده‌های اشاره‌گر است، اما برعکس صدق نمی‌کند
  • قوانین
    • اشیاء مقدار تنها می‌توانند از مجموعه متدهای دارای گیرنده‌های مقدار استفاده کنند
    • اشیاء اشاره‌گر می‌توانند از مجموعه متدهای دارای گیرنده‌های مقدار + مجموعه متدهای دارای گیرنده‌های اشاره‌گر استفاده کنند
  • بازتاب رابط (یا پیاده‌سازی)
    • نوع با رابط هم‌خوانی دارد اگر همه متدهای رابط را پیاده‌سازی کند
    • به‌طور خاص، یا مجموعه متدهای مقدار نوع با متدهای رابط هم‌خوانی دارد یا مجموعه متدهای اشاره‌گر با رابط هم‌خوانی دارد

دو نوع خاص از هم‌خوانی وجود دارد:

  • هم‌خوانی مجموعه متدهای مقدار با رابط
    • مجموعه متدهای مقدار وجود دارد، امکان اختصاص یک اشیاء مقدار یا اشاره‌گر به یک متغیر رابطی وجود دارد، زیرا هر دو حاوی مجموعه متدهای مقدار هستند
  • هم‌خوانی مجموعه متدهای اشاره‌گر با رابط
    • تنها یک اشیاء اشاره‌گر می‌تواند به یک متغیر رابطی اختصاص داده شود، زیرا تنها مجموعه متدهای اشاره‌گر با رابط هم‌خوانی دارد
    • اگر یک اشیاء مقدار به یک متغیر رابطی اختصاص داده شود، در طول اجرا، مکانیزم بررسی زنده رابط به وجود خواهد آمد

در مورد اینکه چرا i = s2Val خطایی ایجاد می‌کند، دلیل آن این است که مجموعه متدهای مقدار و رابط هماهنگی ندارند.